home *** CD-ROM | disk | FTP | other *** search
Wrap
/* // Permission to use, copy, modify, and distribute this software and its // documentation for any purpose and without fee is hereby granted, provided // that the above copyright notice appear in all copies and that both that // copyright notice and this permission notice appear in supporting // documentation, and that the name of I.B.M. not be used in advertising // or publicity pertaining to distribution of the software without specific, // written prior permission. I.B.M. makes no representations about the // suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. // // I.B.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL I.B.M. // BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // Author: Barry Minor, IBM AWS Graphics Systems (Austin) // minor@austin.ibm.com // // Special Thanks to .. // // John Dennis of DEC // Bob Arenburg of IBM // Rob Putney of IBM // Dale Kirkland of Intergraph // Hock Lee of Microsoft // Tom McReynolds of SGI // John Spitzer of SGI // // and the OPC committee // for their help in completing this project */ #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #ifdef CRAY #include <rpc/types.h> #include <rpc/xdr.h> #endif #if defined(OS2) || defined(WIN32) #include <stdarg.h> #else #include <unistd.h> #endif #include <math.h> #include <stdlib.h> #ifdef WIN32 #include <windows.h> #endif #include <GL/gl.h> #if defined(WIN32) || defined(__amigaos__) #include <GL/glaux.h> #else #include "aux.h" #endif #include "viewperf.h" #include "bfont.h" #include "vpProtos.h" #include "plyJT.h" #include "mshJT.h" #include "triJT.h" #include "qadJT.h" #include "evtJT.h" #include "Env.h" #ifdef WIN32 static FILE *LogFile; #endif #if defined(WIN32) || defined(OS2) #define BINARY_FILE "rb" #else #define BINARY_FILE "r" #endif #ifdef __hpux #include "limits.h" #endif #ifdef MP int numProcessors (); #endif /* Function Pointers */ void (*eventloop)(int thread); void fill_mesh(struct mesh *msh, FILE *f, GLenum swapFlag, float *min, float *max); void read_colors(struct colorvector * vcolor, FILE *f); void calculate_colors(struct colorvector * vcolor, struct vector * verts, GLfloat * trans, GLfloat maxmag, GLfloat minmag); void compare_min_max(struct vector * verts, GLfloat * trans, GLfloat *minmag, GLfloat *maxmag); void compute_bounds(GLfloat *center, GLfloat *trans, GLfloat *min, GLfloat *max); void get_colors_msh(struct mesh *msh, int np, GLfloat *trans, char *objnameptr); void get_colors_ply(struct vector *vert, struct colorvector *vcolor, int numverts, GLfloat *trans, char *objnameptr); void get_colors_triquad(struct vector *vert, struct colorvector *vcolor, int numverts, GLfloat *trans, char *objnameptr); /* Global Variables */ struct EventBlock eventblock; GLfloat iang=0.0, jang=0.0, kang=0.0; char rendermodetext[][16] = { "TMESH", "VECTOR", "LINE", "POINT", "POLYGON", "TFAN", "TRIANGLE", "QUAD" }; int BatchTable[] = { BM_NO_BATCH, /* TMESHmode */ BM_BATCH_BY_TWO, /* VECTORmode */ BM_NO_BATCH, /* LINEmode */ BM_BATCH_ALL, /* POINTmode */ BM_NO_BATCH, /* POLYGONmode */ BM_NO_BATCH, /* TFANmode */ BM_BATCH_ALL, /* TRImode */ BM_BATCH_ALL /* QUADmode */ }; /*********************************************************************/ /* */ /* text strings for reporting */ /* */ /*********************************************************************/ char txfile[100] = "NONE"; char txmin[30] = "NEAREST"; char txmag[30] = "NEAREST"; char txenv[30] = "DECAL"; char txsblendfunc[40] = "SRC_ALPHA"; char txdblendfunc[40] = "ONE_MINUS_SRC_ALPHA"; char txtoggle[40] = "NONE"; char txcriteria[10] = "MINIMUM"; char txpmf[10] = "FILL"; char txpmb[10] = "FILL"; char txcolormode[30] = "COLOR_PER_FRAME"; char teststring[][32] = { "FRAME", "PRIMITIVE", "VERTEX" }; char extension[][8] = { ".coo", ".ele", ".vnm", ".clr", ".msh", ".bin", ".wlk" }; char falsetrue[][8] = { "FALSE", "TRUE" }; char texture_generation_mode[][32] = { "NO_TEXTURE_GENERATION", "EYE_LINEAR", "OBJECT_LINEAR", "SPHERE_MAP" }; char cmfaceString[64] = "FRONT"; char cmmodeString[64] = "AMBIENT_AND_DIFFUSE"; static char cmdln[400]; static char desc[400]; /* text for test description */ static char *bf[] = { "" , "-bf " }; static char *ff[] = { "" , "-ff " }; static char *ls[] = { "" , "-ls " }; static char *fn[] = { "" , "-fn " }; static char *dl[] = { "" , "-dl " }; static char *shade[] = { "" , "-f " }; static char *dr[] = { "-ir " , "" }; static char *vac[] = { "" , "-vac " }; static char *val[] = { "" , "-val " }; static char *vz[] = { "" , "-vz " }; static char *vst[] = { "" , "-vst " }; static char *db[] = { "-sb " , "" }; static char *or[] = { "" , "-or " }; static char *di[] = { "-ndi" , "" }; static char *bl[] = { "" , "-bl " }; static char *zb[] = { "" , "-zb " }; static char *lp[] = { "" , "-lp " }; static char *pp[] = { "" , "-pp " }; static char *fg[] = { "" , "-fg " }; static char *clip[] = { "" , "-c " }; static char *l2s[] = { "" , "-l2s " }; static char *lv[] = { "" , "-lv " }; static char *ll[] = { "" , "-ll " }; static char *ps[] = { "" , "-ps " }; static char *cptx[] = { "FRAME ", "PRIMITIVE ", "VERTEX "}; static char *inputmodetx[] = { "", "-pg ", "-mh ", "-tr ", "-qd "}; static unsigned int stipple[32] = { 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555 }; static GLfloat maxdim; static int vertsperframe; #if defined(WIN32) void APIENTRY FinishFrame(HDC hdc) { glFinish(); } #elif defined(OS2) || defined(__amigaos__) void FinishFrame(void) { glFinish(); } #else void FinishFrame(Display *dpy, GLXDrawable drawable) { glFinish(); } #endif /*********************************************************************/ /* */ /* Swap for all you LITTLE_ENDIAN fans out there */ /* Use this to convert binary files to LITTLE_ENDIAN format */ /* */ /*********************************************************************/ void Swap32(void *ptr, long length) { register GLuint tmp; /* GLuint should be typedef'ed to 32 bit unsigned int */ GLuint i, *array = (GLuint * ) ptr; for (i = 0; i < length; i++) { tmp = array[i]; tmp &= 0xffffffff; tmp = ((tmp >> 24) | (tmp << 24) | ((tmp >> 8) & 0xff00) | ((tmp << 8) & 0xff0000)); array[i] = tmp; } } /*********************************************************************/ /* */ /* Convert GL error enums to text strings for output */ /* */ /*********************************************************************/ char *error2str(GLenum err) { switch (err) { case GL_INVALID_ENUM: return("GL_INVALID_ENUM"); case GL_INVALID_VALUE: return("GL_INVALID_VALUE"); case GL_INVALID_OPERATION: return("GL_INVALID_OPERATION"); case GL_STACK_OVERFLOW: return("GL_STACK_OVERFLOW"); case GL_STACK_UNDERFLOW: return("GL_STACK_UNDERFLOW"); case GL_OUT_OF_MEMORY: return("GL_OUT_OF_MEMORY"); } } /*********************************************************************/ /* */ /* Convert HSV color space to RGB */ /* Used to create vertex colors for data sets */ /* */ /*********************************************************************/ hsv_to_rgb(GLfloat h, GLfloat s, GLfloat v, GLfloat *r, GLfloat *g, GLfloat *b) { int i; GLfloat f, p, q, t; if (s == 0.0) { *r = v; *g = v; *b = v; } else { h = fmod(h, 1.); h *= 6.; i = (int) floor(h); f = h - i; p = v * (1 - s); q = v * (1 - (s * f)); t = v * (1 - (s * (1 - f))); switch (i) { case 0 : *r = v; *g = t; *b = p; break; case 1 : *r = q; *g = v; *b = p; break; case 2 : *r = p; *g = v; *b = t; break; case 3 : *r = p; *g = q; *b = v; break; case 4 : *r = t; *g = p; *b = v; break; case 5 : *r = v; *g = p; *b = q; break; } } } #ifdef SEARCHPATH /*********************************************************************/ /* */ /* Find a path of a particular file */ /* */ /*********************************************************************/ char* SearchPath(const char* path, const char* file) { static char fullpath[512]; char filename[512]; char* tmppath; char searchpath[512]; FILE *f; strcpy(searchpath, path); for (tmppath = strtok(searchpath, ":"); tmppath; tmppath = strtok(NULL, ":")) { if (*tmppath == 0) { strcpy(filename, "."); } else { strcpy(filename, tmppath); } strcat(filename, "/"); strcat(filename, file); if (f = fopen(filename, "r")) { fclose(f); strcpy(fullpath, tmppath); return fullpath; } } return NULL; } #endif /*********************************************************************/ /* */ /* Compute texture coordinates for polygon data sets */ /* Creates a spherical mapping based on vertex normals */ /* */ /*********************************************************************/ int param_poly(struct EventBlock *pevent) { int i; double phi, theta; double basex, basey, basemag; double uu, ww; struct vector *texture; struct vector *vnorm = pevent->rb->vnorm; int numverts = pevent->rb->numverts; texture = pevent->rb->texture = (struct vector *)malloc((numverts + 1) * sizeof(struct vector )); for (i = 1; i <= numverts; i++) { /* calculate location in texture map */ phi = acos(((double) vnorm[i].z)); basemag = sqrt((double)vnorm[i].x * (double)vnorm[i].x + (double)vnorm[i].y * (double)vnorm[i].y); if (basemag == 0.0) { basex = 0.0; basey = 0.0; } else { basex = vnorm[i].x / basemag; basey = vnorm[i].y / basemag; } theta = asin((double)basey); if (basex < 0.0) theta = PI - theta; if (theta < 0.0) theta += 2.0 * PI; uu = theta / (2.0 * PI); ww = phi / (PI); texture[i].x = (GLfloat)uu; texture[i].y = (GLfloat)ww; } } /*********************************************************************/ /* */ /* Compute texture coordinates for mesh data sets */ /* Creates a spherical mapping based on vertex normals */ /* */ /*********************************************************************/ int param_mesh(struct EventBlock *pevent) { int i, k; GLfloat phi, theta; double basex, basey, basemag; GLfloat uu, ww; struct mesh *msh = pevent->rb->msh; struct vector *norms; struct vector *texture; int *np = &pevent->rb->np; for (i = 0; i < *np; i++) { norms = msh[i].norms; texture = msh[i].texture; for (k = 0; k < msh[i].numverts; ++k) { /* calculate location in texture map */ phi = acos((double)norms[k].z); basemag = sqrt((double)norms[k].x * (double)norms[k].x + (double)norms[k].y * (double)norms[k].y); if (basemag == 0.0) { basex = 0.0; basey = 0.0; } else { basex = msh[i].norms[k].x / basemag; basey = msh[i].norms[k].y / basemag; } theta = asin((double)basey); if (basex < 0.0) theta = PI - theta; if (theta < 0.0) theta += 2.0 * PI; uu = theta / (2.0 * PI); ww = phi / (PI); texture[k].x = (GLfloat)uu; texture[k].y = (GLfloat)ww; } } } /*********************************************************************/ /* */ /* meshinput reads in mesh data sets and computes vertex data */ /* */ /*********************************************************************/ void meshinput(char *objnameptr, struct EventBlock *pevent) { union { int testWord; char testByte[4]; } endianTest; GLenum swapFlag; int binary_version, datatype; int i, k; int nummesh; FILE * f; char filename[512], *filenameptr; int tempspace[100]; GLfloat maxmag, minmag, vertmag; GLfloat tmp; int cvcount; int nRead; struct vector *dummybuffer; GLfloat * trans = pevent->trans; GLfloat * center = pevent->center; struct mesh *msh; int *np = &pevent->rb->np; float max[3], min[3]; #ifdef CRAY XDR xdr_handle; XDR *xdrs = &xdr_handle; float fbuf[3]; #endif endianTest.testWord = 1; if (endianTest.testByte[0] == 1) { swapFlag = GL_TRUE; } else { swapFlag = GL_FALSE; } *np = 0; filenameptr = filename; for (i = 0; i < 3; i++) { max[i] = SMALL; min[i] = BIG; } filenameptr = strcpy(filenameptr, objnameptr); /* Check to see if binary file format is present */ filenameptr = strcat(filenameptr, extension[5]); if ((f = fopen(filename, BINARY_FILE))) { nRead = fread(&binary_version, sizeof(unsigned int), 1, f); if(nRead == 0) { FATAL_ERROR("unexpected end of input in binary file\n"); } switch(binary_version) { case 0: nRead = fread(&datatype, sizeof(GLenum),1,f); if(nRead != 1) FATAL_ERROR("Unexpected end of input\n"); if(datatype != GL_TRIANGLE_STRIP) { FATAL_ERROR("primitive type is not a triangle mesh\n"); } nRead = fread(np, sizeof(int), 1, f); if(nRead != 1) FATAL_ERROR("Unexpected end of input\n"); msh = pevent->rb->msh = (struct mesh*)malloc(*np *sizeof(struct mesh)); #ifdef CRAY xdrstdio_create(xdrs, f, XDR_DECODE); #endif for(nummesh = 0; nummesh < *np; ++nummesh) { fill_mesh(&(msh[nummesh]), f, swapFlag, min, max); } #ifdef CRAY xdr_destroy(xdrs); #endif fclose(f); compute_bounds(center, trans, min, max); get_colors_msh(msh, *np, trans, objnameptr); break; default: printf("Unrecognized binary version %u", binary_version); exit(1); break; } } else { filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[4]); if((f = fopen(filename, BINARY_FILE)) == NULL) { printf("Couldn't open (.msh) input file %s\n", filename); exit(1); } /* Read through one to get a count */ #ifndef CRAY while ((nRead = fread(&cvcount, sizeof(GLint), 1, f)) > 0) { if (swapFlag) Swap32((void *) & cvcount, 1); dummybuffer = (struct vector *) malloc(cvcount * sizeof(struct vector )); nRead = fread(dummybuffer, cvcount * sizeof(GLfloat) * 3, 1, f); if (nRead == 0) { FATAL_ERROR("unexpected end of input in .msh file\n"); } if (nRead < 0) { FATAL_ERROR("read error getting mesh\n"); } nRead = fread(dummybuffer, cvcount * sizeof(GLfloat) * 3, 1, f); if (nRead == 0) { FATAL_ERROR("unexpected end of input\n"); } if (nRead < 0) { FATAL_ERROR("read error getting mesh\n"); } free(dummybuffer); (*np)++; } if (nRead < 0) { FATAL_ERROR("read error getting mesh\n"); } #else xdrstdio_create(xdrs, f, XDR_DECODE); while (xdr_int(xdrs, &cvcount)) { for (i = 0; i < cvcount; i++) { if (!xdr_vector(xdrs, (void *)&fbuf, 3, sizeof(float), xdr_float)) { FATAL_ERROR("unexpected end of input\n"); } if (!xdr_vector(xdrs, (void *)&fbuf, 3, sizeof(float), xdr_float)) { FATAL_ERROR("unexpected end of input\n"); } } (*np)++; } xdr_destroy(xdrs); #endif fclose(f); if((f = fopen(filename, BINARY_FILE)) == 0) { FATAL_ERROR("Couldn't open (msh) input file\n"); } /* malloc space for structure and fill it in */ msh = pevent->rb->msh = (struct mesh *)malloc(*np * sizeof(struct mesh )); #ifdef CRAY xdrstdio_create(xdrs, f, XDR_DECODE); #endif for (nummesh = 0; nummesh < *np; ++nummesh) { fill_mesh(&(msh[nummesh]), f, swapFlag, min, max); } #ifdef CRAY xdr_destroy(xdrs); #endif fclose(f); /* Compute bounding box info for data set */ compute_bounds(center, trans, min, max); /* Compute vertex colors */ get_colors_msh(msh, *np, trans, objnameptr); } /* count the number of vertex calls per frame */ vertsperframe = 0; for (i = 0; i < *np; i++) { vertsperframe += msh[i].numverts; } } void get_colors_msh(struct mesh *msh, int np, GLfloat *trans, char *objnameptr) { GLfloat maxmag = SMALL; GLfloat minmag = BIG; int i, k; FILE *f; char filename[512], *filenameptr; filenameptr = filename; filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[3]); if(f = fopen(filename, BINARY_FILE)) { for (i = 0; i < np; i++) { for (k = 0; k < msh[i].numverts; ++k) { read_colors(&(msh[i].vcolor[k]), f); } } fclose(f); } else { for (i = 0; i < np; i++) { for (k = 0; k < msh[i].numverts; ++k) { compare_min_max(&(msh[i].verts[k]), trans, &minmag, &maxmag); } } for (i = 0; i < np; i++) { for (k = 0; k < msh[i].numverts; ++k) { calculate_colors(&(msh[i].vcolor[k]), &(msh[i].verts[k]), trans, maxmag, minmag); } } } } void compute_bounds(GLfloat *center, GLfloat *trans, GLfloat *min, GLfloat *max) { center[0] = (max[0] - min[0]); center[1] = (max[1] - min[1]); center[2] = (max[2] - min[2]); maxdim = sqrt((double)(center[0] * center[0] + center[1] * center[1] + center[2] * center[2])) / 2.0F; trans[3] = maxdim; center[0] /= 2.0F; /* don't move look up - need half dim */ center[1] /= 2.0F; center[2] /= 2.0F; trans[0] = min[0] + center[0]; trans[1] = min[1] + center[1]; trans[2] = min[2] + center[2]; } void compare_min_max(struct vector * verts, GLfloat * trans, GLfloat *minmag, GLfloat *maxmag) { GLfloat vertmag; vertmag = sqrt((double)(verts->x - trans[0]) * (verts->x - trans[0]) + (verts->y - trans[1]) * (verts->y - trans[1]) + (verts->z - trans[2]) * (verts->z - trans[2])); if (vertmag > *maxmag) *maxmag = vertmag; if (vertmag < *minmag) *minmag = vertmag; } void calculate_colors(struct colorvector * vcolor, struct vector * verts, GLfloat * trans, GLfloat maxmag, GLfloat minmag) { GLfloat r, g, b, d; GLfloat vertmag; vertmag = sqrt((double)((verts->x - trans[0]) * (verts->x - trans[0]) + (verts->y - trans[1]) * (verts->y - trans[1]) + (verts->z - trans[2]) * (verts->z - trans[2]))); d = maxmag - vertmag; if (d == 0.0) vertmag = 1.0; else vertmag = (maxmag - minmag) / d; hsv_to_rgb(vertmag, 1.0, 1.0, &r, &g, &b); vcolor->r = r; vcolor->g = g; vcolor->b = b; vcolor->a = 0.5; } void read_colors(struct colorvector * vcolor, FILE *f) { float r, g, b, a; int nRead; nRead = 0; nRead += fread(&r, sizeof(float), 1, f); nRead += fread(&g, sizeof(float), 1, f); nRead += fread(&b, sizeof(float), 1, f); nRead += fread(&a, sizeof(float), 1, f); if(nRead != 4) { FATAL_ERROR("read error in color file"); } #ifdef LITTLE_ENDIAN Swap32(&r, 1); Swap32(&g, 1); Swap32(&b, 1); Swap32(&a, 1); #endif vcolor->r = r; vcolor->g = g; vcolor->b = b; vcolor->a = a; } void fill_mesh(struct mesh *msh, FILE *f, GLenum swapFlag, float *min, float*max) { int cvcount; int i; #ifndef CRAY fread(&cvcount, sizeof(GLint), 1, f); if (swapFlag) Swap32((void *) & cvcount, 1); #else xdr_int(xdrs, &cvcount); #endif msh->numverts = cvcount; msh->verts = (struct vector *) malloc(cvcount * sizeof(struct vector )); msh->norms = (struct vector *) malloc(cvcount * sizeof(struct vector )); msh->texture = (struct vector *) malloc(cvcount * sizeof(struct vector )); msh->vcolor = (struct colorvector *) malloc(cvcount * sizeof(struct colorvector )); #ifndef CRAY fread(&msh->verts[0].x, cvcount * sizeof(GLfloat) * 3, 1, f); fread(&msh->norms[0].x, cvcount * sizeof(GLfloat) * 3, 1, f); if (swapFlag) { Swap32((void *) & msh->verts[0].x, cvcount * 3); Swap32((void *) & msh->norms[0].x, cvcount * 3); } #else xdr_vector(xdrs, (void *)&msh->verts[0].x, cvcount * 3, sizeof(float), xdr_float); xdr_vector(xdrs, (void *)&msh->norms[0].x, cvcount * 3, sizeof(float), xdr_float); #endif for (i = 0; i < cvcount; i++) { if (msh->verts[i].x > max[0]) max[0] = msh->verts[i].x; else if (msh->verts[i].x < min[0]) min[0] = msh->verts[i].x; if (msh->verts[i].y > max[1]) max[1] = msh->verts[i].y; else if ( msh->verts[i].y < min[1]) min[1] = msh->verts[i].y; if (msh->verts[i].z > max[2]) max[2] = msh->verts[i].z; else if (msh->verts[i].z < min[2]) min[2] = msh->verts[i].z; } } /*********************************************************************/ /* */ /* polygoninput reads in polygon data sets and computes vertex data */ /* */ /*********************************************************************/ void polygoninput(char *objnameptr, struct EventBlock *pevent) { int i; FILE * f; int numverts; int numpoly; char filename[512], *filenameptr; int tempspace[100]; GLfloat maxmag, minmag, vertmag; GLfloat tmp; char name[1024]; int nRead; int index, colorflag; GLfloat dummy[3]; GLfloat * trans = pevent->trans; GLfloat * center = pevent->center; struct vector *vert; struct vector *vnorm; struct colorvector *vcolor; struct plygon *ply; int *np = &pevent->rb->np; float max[3], min[3]; int binary_file = 0; int binary_version, datatype; *np = 0; filenameptr = filename; for (i = 0; i < 3; i++) { max[i] = SMALL; min[i] = BIG; } filenameptr = strcpy(filenameptr, objnameptr); /* Check to see if binary file format is present */ filenameptr = strcat(filenameptr, extension[5]); if ((f = fopen(filename, BINARY_FILE))) { binary_file = 1; nRead = fread(&binary_version, sizeof(unsigned int), 1, f); if(nRead == 0) { FATAL_ERROR("unexpected end of input in binary file\n"); } switch(binary_version) { case 0: nRead = fread(&datatype, sizeof(GLenum),1,f); if(nRead != 1) FATAL_ERROR("Unexpected end of input\n"); if(datatype != GL_POLYGON) { FATAL_ERROR("primitive type is not a polygon\n"); } nRead = fread(np, sizeof(int), 1, f); if(nRead != 1) FATAL_ERROR("Unexpected end of input\n"); ply = pevent->rb->ply = (struct plygon *)malloc((*np) * sizeof(struct plygon )); for(numpoly = 0; numpoly < *np; ++numpoly) { fread(&(ply[numpoly].numverts), sizeof(int), 1, f); if(ply[numpoly].numverts <= 0) FATAL_ERROR("Negative primitive size\n"); ply[numpoly].index = (int *)malloc(ply[numpoly].numverts * sizeof(int)); fread(ply[numpoly].index, sizeof(int), ply[numpoly].numverts, f); } nRead = fread(&numverts, sizeof(int), 1, f); if(nRead != 1) FATAL_ERROR("Unexpected end of input\n"); if(numverts <= 0) FATAL_ERROR("Negative number of vertexes\n"); vert = pevent->rb->vert = (struct vector *)malloc(numverts*sizeof(struct vector)); vnorm = pevent->rb->vnorm = (struct vector *)malloc(numverts*sizeof(struct vector)); vcolor = pevent->rb->vcolor = (struct colorvector *)malloc(numverts*sizeof(struct colorvector)); fread(vert, sizeof(struct vector), numverts, f); fread(vnorm, sizeof(struct vector), numverts, f); for(i=0; i < numverts; i++) { if(vert[i].x > max[0]) max[0] = vert[i].x; else if (vert[i].x < min[0]) min[0] = vert[i].x; if(vert[i].y > max[1]) max[1] = vert[i].y; else if (vert[i].x < min[1]) min[1] = vert[i].y; if(vert[i].z > max[2]) max[0] = vert[i].z; else if (vert[i].z < min[2]) min[2] = vert[i].z; } compute_bounds(center, trans, min, max); get_colors_ply(vert, vcolor, numverts, trans, objnameptr); break; default: printf("Unrecognized binary version %u", binary_version); exit(1); break; } } else { /* Open .coo file - vertex info */ filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[0]); if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (coo) input file\n"); } /* Read once to get a count */ numverts = 0; while ((nRead = fscanf(f, "%d", &index)) == 1) { nRead = fscanf(f, ",%f,%f,%f", &dummy[0], &dummy[1], &dummy[2]); if (nRead == EOF) { FATAL_ERROR("unexpected end of input\n"); } if (nRead != 3) { FATAL_ERROR("read error getting polygon input\n"); } numverts++; } if (nRead != EOF) { FATAL_ERROR("read error getting polygon input\n"); } fclose(f); pevent->rb->numverts = numverts; if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (coo) input file\n"); } /* malloc space and fill it in */ vert = pevent->rb->vert = (struct vector *)malloc((numverts+1)*sizeof(struct vector )); for (i = 1; i <= numverts; i++) { fscanf(f, "%d", &index); fscanf(f, ",%f,%f,%f", &(vert[index].x), &(vert[index].y), &(vert[index].z)); if (vert[index].x > max[0]) max[0] = vert[index].x; else if (vert[index].x < min[0]) min[0] = vert[index].x; if (vert[index].y > max[1]) max[1] = vert[index].y; else if (vert[index].y < min[1]) min[1] = vert[index].y; if (vert[index].z > max[2]) max[2] = vert[index].z; else if (vert[index].z < min[2]) min[2] = vert[index].z; } /* Open .ele file - connectivity info */ fclose(f); filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[1]); if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (ele) input file\n"); } /* Read once to get a count */ while ((nRead = fscanf(f, "%s ", name)) == 1) { i = 0; while ((nRead = fscanf(f, "%d ", &tempspace[i])) == 1) i++; if (i > 0) { (*np)++; } } if (nRead != EOF) { FATAL_ERROR("read error getting polygon input\n"); } fclose(f); /* malloc space and fill it in */ ply = pevent->rb->ply = (struct plygon *)malloc((*np) * sizeof(struct plygon )); if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (ele) input file\n"); } for (numpoly = 0; numpoly < *np; ++numpoly) { fscanf(f, "%s ", name); i = 0; while ((nRead = fscanf(f, "%d ", &tempspace[i])) == 1) i++; if (i > 0) { ply[numpoly].numverts = i; ply[numpoly].index = (int *) malloc(i * sizeof(int)); for (i = 0; i < ply[numpoly].numverts; i++) ply[numpoly].index[i] = (int) tempspace[i]; } } fclose(f); /* Open .vnm file - vertex normals */ filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[2]); /* already have count so malloc space and fill it in */ vnorm = pevent->rb->vnorm = (struct vector *)malloc((numverts + 1) * sizeof(struct vector )); if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (vnm) input file\n"); } for (i = 1; i <= numverts; i++) nRead = fscanf(f, "%f %f %f\n", &vnorm[i].x, &vnorm[i].y, &vnorm[i].z); if (nRead != 3) { FATAL_ERROR("read error in .vnm file\n"); } fclose(f); /* Compute bounding box info */ compute_bounds(center, trans, min, max); /* compute vertex color and fill them in */ vcolor = pevent->rb->vcolor = (struct colorvector *)malloc((numverts+1)*sizeof(struct colorvector )); get_colors_ply(vert, vcolor, numverts, trans, objnameptr); } /* count the number of vertex calls per frame */ vertsperframe = 0; for (i = 0; i < *np; i++) { vertsperframe += ply[i].numverts; } } void get_colors_ply(struct vector *vert, struct colorvector *vcolor, int numverts, GLfloat *trans, char *objnameptr) { int colorflag; GLfloat maxmag = SMALL; GLfloat minmag = BIG; int i; FILE * f; char filename[512], *filenameptr; filenameptr = filename; filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[3]); if((f = fopen(filename, BINARY_FILE)) == 0) { colorflag = 0; } else { colorflag = 1; } if (!colorflag) { for (i = 1; i <= numverts; i++) { compare_min_max(&(vert[i]), trans, &minmag, &maxmag); } } for (i = 1; i <= numverts; i++) { if(colorflag) { read_colors(&(vcolor[i]), f); } else { calculate_colors(&(vcolor[i]), &(vert[i]), trans, maxmag, minmag); } } if(colorflag) fclose(f); } GLfloat MinAngle( GLfloat from, GLfloat to) { GLfloat delta = to - from; if (fabs(delta) > 180.) { return (from > to) ? delta + 360. : delta - 360.; } else { return delta; } } void walkthruinput(char *objnameptr, struct EventBlock *pevent) { FILE *fp; char filename[512], *filenameptr; GLfloat eyeX, eyeY, eyeZ; GLfloat p_eyeX, p_eyeY, p_eyeZ; GLfloat heading, p_heading; GLfloat pitch, p_pitch; GLfloat roll, p_roll; int frame; int p_frame; int f; const int sizeInc = 10; int size = sizeInc; GLfloat **walkthru = (GLfloat**)malloc(sizeof(GLfloat*)*size); GLfloat dt, dex, dey, dez, dh, dp, dr; filenameptr = filename; filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[6]); if ((fp = fopen(filename, "r"))) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); while (fscanf(fp, "%d %f %f %f %f %f %f", &frame, &eyeX, &eyeY, &eyeZ, &heading, &pitch, &roll) !=EOF) { if (frame > 0) { dt = frame - p_frame; dex = (eyeX - p_eyeX)/dt; dey = (eyeY - p_eyeY)/dt; dez = (eyeZ - p_eyeZ)/dt; dh = MinAngle(p_heading, heading)/dt; dp = MinAngle(p_pitch, pitch)/dt; dr = MinAngle(p_roll, roll)/dt; for (f = p_frame; f < frame; f++) { float i = f - p_frame; glPushMatrix(); glRotatef(-90.0, 1.0, 0.0, 0.0); glRotatef(-(p_roll + i * dr), 0.0, 1.0, 0.0); glRotatef(-(p_pitch + i * dp), 1.0, 0.0, 0.0); glRotatef(-(p_heading + i * dh), 0.0, 0.0, 1.0); glTranslatef( -(p_eyeX + i * dex), -(p_eyeY + i * dey), -(p_eyeZ + i * dez) ); if (f == size) { size += sizeInc; walkthru = (GLfloat**)realloc(walkthru, sizeof(GLfloat*)*size); } walkthru[f] = (GLfloat*)malloc(sizeof(GLfloat)*16); glGetFloatv(GL_MODELVIEW_MATRIX, walkthru[f]); glPopMatrix(); } } p_frame = frame; p_eyeX = eyeX; p_eyeY = eyeY; p_eyeZ = eyeZ; p_heading = heading; p_pitch = pitch; p_roll = roll; } glPopMatrix(); if (pevent->numframes == 0) { pevent->numframes = frame; } else if (pevent->numframes > frame) { FATAL_ERROR("viewperf: -numframes greater than defined positions in walkthru file\n"); } pevent->walkthru = walkthru; } else { FATAL_ERROR("viewperf: could not find walkthru file\n"); } } /*********************************************************************/ /* */ /* triquadinput reads in triangle and quad data sets and computes */ /* vertex data */ /* */ /*********************************************************************/ void triquadinput(char *objnameptr, int vertsperobj, struct EventBlock *pevent) { int i; FILE * f; int numverts; int numpoly; char filename[512], *filenameptr; int tempspace[4]; GLfloat maxmag, minmag, vertmag; GLfloat tmp; char name[1024]; int nRead; int index, colorflag; GLfloat dummy[3]; GLfloat * trans = pevent->trans; GLfloat * center = pevent->center; struct vector *vert; struct vector *vnorm; struct colorvector *vcolor; struct plygon *ply; int *np = &pevent->rb->np; float max[3], min[3]; unsigned binary_version; GLenum datatype; *np = 0; filenameptr = filename; for (i = 0; i < 3; i++) { max[i] = SMALL; min[i] = BIG; } filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[5]); if((f = fopen(filename, BINARY_FILE))) { nRead = fread(&binary_version, sizeof(unsigned int), 1, f); if(nRead == 0) { FATAL_ERROR("Unexpected end of input in binary file\n"); } switch(binary_version) { case 0: nRead = fread(&datatype, sizeof(GLenum), 1, f); if(nRead != 1) FATAL_ERROR("Unexpected end of input\n"); if(!(((datatype == GL_TRIANGLES) && (vertsperobj == 3)) || ((datatype == GL_QUADS)) && (vertsperobj == 4))) { FATAL_ERROR("primitive type not triangles or quads\n"); } fread(&numverts, sizeof(unsigned), 1, f); pevent->rb->numverts = numverts; if(nRead != 1) FATAL_ERROR("Unexpected end of input\n"); vert = pevent->rb->vert = (struct vector *)malloc((numverts+1)*sizeof(struct vector)); fread(&vert[1], sizeof(struct vector), numverts, f); for(i=1; i <= numverts; i++) { if (vert[i].x > max[0]) max[0] = vert[i].x; else if (vert[i].x < min[0]) min[0] = vert[i].x; if (vert[i].y > max[1]) max[1] = vert[i].y; else if (vert[i].y < min[1]) min[1] = vert[i].y; if (vert[i].z > max[2]) max[2] = vert[i].z; else if (vert[i].z < min[2]) min[2] = vert[i].z; } *np = numverts / vertsperobj; vnorm = pevent->rb->vnorm = (struct vector *)malloc(numverts*sizeof(struct vector)); fread(vert, sizeof(struct vector), numverts, f); ply = pevent->rb->ply = (struct plygon *)malloc((*np) * sizeof(struct plygon )); for(numpoly = 0; numpoly < *np; ++numpoly) { ply[numpoly].numverts = vertsperobj; ply[numpoly].index = (int *)malloc(vertsperobj *sizeof(int)); fread(ply[numpoly].index, sizeof(int), vertsperobj, f); } compute_bounds(center, trans, min, max); vcolor = pevent->rb->vcolor = (struct colorvector*)malloc((numverts)*sizeof(struct colorvector)); get_colors_triquad(vert, vcolor, numverts, trans, objnameptr); fclose(f); break; default: printf("Unrecognized binary version %u", binary_version); exit(1); break; } } else { /* Open .coo file - vertex info */ filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[0]); if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (coo) input file\n"); } /* Read once to get a count */ numverts = 0; while ((nRead = fscanf(f, "%d", &index)) == 1) { nRead = fscanf(f, ",%f,%f,%f", &dummy[0], &dummy[1], &dummy[2]); if (nRead == EOF) { FATAL_ERROR("unexpected end of input\n"); } if (nRead != 3) { FATAL_ERROR("read error in .coo file\n"); } numverts++; } if (nRead != EOF) { FATAL_ERROR("read error in .coo file (2)\n"); } fclose(f); /* malloc space and fill it in */ vert = pevent->rb->vert = (struct vector *)malloc((numverts + 1) * sizeof(struct vector )); pevent->rb->numverts = numverts; if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (coo) input file\n"); } for (i = 1; i <= numverts; i++) { fscanf(f, "%d", &index); fscanf(f, ",%f,%f,%f", &(vert[index].x), &(vert[index].y), &(vert[index].z)); if (vert[i].x > max[0]) max[0] = vert[i].x; else if (vert[i].x < min[0]) min[0] = vert[i].x; if (vert[i].y > max[1]) max[1] = vert[i].y; else if (vert[i].y < min[1]) min[1] = vert[i].y; if (vert[i].z > max[2]) max[2] = vert[i].z; else if (vert[i].z < min[2]) min[2] = vert[i].z; } fclose(f); /* Open .ele file - connectivity info */ filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[1]); if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (ele) input file\n"); } while ((nRead = fscanf(f, "%s ", name)) == 1) { i = 0; while ((nRead = fscanf(f, "%d ", &tempspace[i])) == 1) i++; if (i != vertsperobj) { FATAL_ERROR("Input file doesn't match input type\n"); } if (i > 0) { (*np)++; } } if (nRead != EOF) { FATAL_ERROR("read error in .ele file\n"); } fclose(f); /* malloc space and fill it in */ ply = pevent->rb->ply = (struct plygon *)malloc((*np) * sizeof(struct plygon )); if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (ele) input file\n"); } for (numpoly = 0; numpoly < *np; ++numpoly) { fscanf(f, "%s ", name); ply[numpoly].numverts = vertsperobj; ply[numpoly].index = (int *) malloc(vertsperobj * sizeof(int)); for (i = 0; i < ply[numpoly].numverts; i++) fscanf(f, "%d ", &ply[numpoly].index[i]); } fclose(f); /* Open .vnm file - vertex normal info */ filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[2]); /* already know how many so malloc and fill in */ vnorm = pevent->rb->vnorm = (struct vector *)malloc((numverts + 1) * sizeof(struct vector )); if ((f = fopen(filename, "r")) == 0) { FATAL_ERROR("Couldn't open (vnm) input file\n"); } for (i = 1; i <= numverts; i++) nRead = fscanf(f, "%f %f %f\n", &vnorm[i].x, &vnorm[i].y, &vnorm[i].z); if (nRead != 3) { FATAL_ERROR("read error in .vnm file\n"); } fclose(f); /* Compute bounding box info */ compute_bounds(center, trans, min, max); /* Compute vertex color, malloc space, and fill it in */ vcolor = pevent->rb->vcolor = (struct colorvector *)malloc((numverts+1)*sizeof(struct colorvector)); get_colors_triquad(vert, vcolor, numverts, trans, objnameptr); } /* Count the number of vertex calls per frame */ vertsperframe = 0; for (i = 0; i < *np; i++) { vertsperframe += ply[i].numverts; } } void get_colors_triquad(struct vector *vert, struct colorvector *vcolor, int numverts, GLfloat *trans, char *objnameptr) { int colorflag; GLfloat maxmag = SMALL; GLfloat minmag = BIG; int i; FILE *f; char filename[512], *filenameptr; filenameptr = filename; filenameptr = strcpy(filenameptr, objnameptr); filenameptr = strcat(filenameptr, extension[3]); if((f = fopen(filename, BINARY_FILE)) == 0) { colorflag = 0; } else colorflag = 1; if(!colorflag) { for (i = 1; i <= numverts; i++) { compare_min_max(&vert[i], trans, &minmag, &maxmag); } } if(colorflag) { for (i = 1; i <= numverts; i++) { read_colors(&vcolor[i], f); } } else { for (i = 1; i <= numverts; i++) { calculate_colors(&vcolor[i], &vert[i], trans, maxmag, minmag); } } if(colorflag) fclose(f); } /*********************************************************************/ /* */ /* Define all material, lighting and lighting model parameters */ /* */ /*********************************************************************/ void SetLightingState(int infiniteLights, int localLights, GLfloat localViewer, GLenum twoSidedLighting, int cmenable, int cmface, int cmmode, int blendOn) { int i; GLfloat normFactor; /* Material settings */ GLfloat materialAmbientColor[4] = { 0.5F, 0.5F, 0.5F, 1.0F }; GLfloat materialDiffuseColor[4] = { 0.7F, 0.7F, 0.7F, 1.0F }; GLfloat materialSpecularColor[4] = { 1.0F, 1.0F, 1.0F, 1.0F }; GLfloat materialShininess[1] = { 128 }; /* Lighting settings */ GLfloat lightPosition[8][4] = { { 1.0F, 1.0F, 1.0F, 1.0F }, { 1.0F, 0.0F, 1.0F, 1.0F }, { 1.0F, -1.0F, 1.0F, 1.0F }, { 0.0F, -1.0F, 1.0F, 1.0F }, { -1.0F, -1.0F, 1.0F, 1.0F }, { -1.0F, 0.0F, 1.0F, 1.0F }, { -1.0F, 1.0F, 1.0F, 1.0F }, { 0.0F, 1.0F, 1.0F, 1.0F } }; GLfloat lightDiffuseColor[8][4] = { { 1.0F, 1.0F, 1.0F, 1.0F }, { 0.0F, 1.0F, 1.0F, 1.0F }, { 1.0F, 0.0F, 1.0F, 1.0F }, { 1.0F, 1.0F, 0.0F, 1.0F }, { 1.0F, 0.0F, 0.0F, 1.0F }, { 0.0F, 1.0F, 0.0F, 1.0F }, { 0.0F, 0.0F, 1.0F, 1.0F }, { 1.0F, 1.0F, 1.0F, 1.0F } }; GLfloat lightAmbientColor[4] = { 0.1F, 0.1F, 0.1F, 1.0F }; GLfloat lightSpecularColor[4] = { 1.0F, 1.0F, 1.0F, 1.0F }; GLfloat lightModelAmbient[4] = { 0.5F, 0.5F, 0.5F, 1.0F }; GLfloat alpha = blendOn ? 0.5F : 1.0F; if (infiniteLights + localLights == 0) return; normFactor = 1.0F / (GLfloat)(infiniteLights + localLights); materialDiffuseColor[3] = alpha; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, materialDiffuseColor); materialAmbientColor[3] = alpha; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, materialAmbientColor); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecularColor); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, materialShininess); lightAmbientColor[0] *= normFactor; lightAmbientColor[1] *= normFactor; lightAmbientColor[2] *= normFactor; for (i = 0; i < localLights + infiniteLights; i++) { lightPosition[i][3] = (GLfloat)(i < localLights); lightDiffuseColor[i][0] *= normFactor; lightDiffuseColor[i][1] *= normFactor; lightDiffuseColor[i][2] *= normFactor; glLightfv(GL_LIGHT0 + i, GL_POSITION, lightPosition[i]); glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lightDiffuseColor[i]); glLightfv(GL_LIGHT0 + i, GL_AMBIENT, lightAmbientColor); glLightfv(GL_LIGHT0 + i, GL_SPECULAR, lightSpecularColor); glEnable(GL_LIGHT0 + i); } glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lightModelAmbient); glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, localViewer); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, twoSidedLighting); if (cmenable) { glColorMaterial(cmface, cmmode); glEnable(GL_COLOR_MATERIAL); } glEnable(GL_LIGHTING); } /*********************************************************************/ /* */ /* Stroke out cute little text for the title screen */ /* */ /*********************************************************************/ DrawString(char *str, GLfloat x, GLfloat y) { short nseg, nstroke; short *cptr; int i, j; glPushMatrix(); glTranslatef (x, y, 0.0F); glScalef (10.0F, 10.0F, 1.0F); while (*str) { cptr = &(chrtbl[*str][0]); nseg = *(cptr++); for (i = 0; i < nseg; i++) { nstroke = *(cptr++); glBegin(GL_LINE_STRIP); for (j = 0; j < nstroke; j++) { glVertex2sv(cptr); cptr += 2; } glEnd(); } glTranslatef (6.0F, 0.0F, 0.0F); str++; } glPopMatrix(); } /*********************************************************************/ /* */ /* rmnoop is plugged into the jump tables where ever there are */ /* holes. They should never be called if everything is working */ /* as planned .. but just in case we'll print an error message. */ /* */ /*********************************************************************/ void rmnoop(struct ThreadBlock *tb) { fprintf(stderr, "This RenderMode is not available for the selected data set\n"); } /*********************************************************************/ /* */ /* Extern routines are plugged into renderers that turn on and off */ /* OpenGL capabilities. These are called once per primitive */ /* through a function pointer. Special "Extern" render routines */ /* have been created that call these functions as part of their */ /* rendering duties. Look in VP_OBJS for their names. */ /* */ /*********************************************************************/ void toggle_capability(GLenum capability) { static int toggleon = 0; if (toggleon = 1 - toggleon) glEnable(capability); else glDisable(capability); } void toggle_linewidth(GLenum dummy) { static GLfloat togglewide = 0.0F; togglewide = 1.0F - togglewide; glLineWidth(togglewide + 1.0F); } void toggle_matrix(GLenum dummy) { static GLfloat matrix[] = { 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F }; glMultMatrixf(matrix); } /*********************************************************************/ /*********************************************************************/ /*********************************************************************/ /*********************************************************************/ /* */ /* Mr. Main */ /* */ /*********************************************************************/ /*********************************************************************/ /*********************************************************************/ /*********************************************************************/ main(int argc, char *argv[]) { char *ptr; char tempstring[512]; GLenum vistype = 0; int i, j, k; int thread; FILE * f, *texfile; int numInfiniteLights = 0; int numLocalLights = 0; GLenum lighttwoside = GL_FALSE; int vis_id = 0; GLenum vis_criteria = AUX_MINIMUM_CRITERIA; int renderDoubleBuffer = VP_TRUE; int colormode = COLOR_PER_FRAME; int inputmode = NOINPUT; int batchmode = VP_FALSE; int numtobatch = 0; int facetnormalmode = VP_FALSE; int linesmoothmode = VP_FALSE; int polysmoothmode = VP_FALSE; int backfacemode = VP_FALSE; int frontfacemode = VP_FALSE; int zbuffermode = VP_FALSE; int fogmode = VP_FALSE; int clipmode = VP_FALSE; GLenum shademodelmode = GL_SMOOTH; int polystipplemode = VP_FALSE; int linestipplemode = VP_FALSE; int togglemode = VP_FALSE; int togglelinewidthmode = VP_FALSE; int togglematrixmode = VP_FALSE; int orthomode = VP_FALSE; int dithermode = VP_TRUE; int texturemode = VP_FALSE; int texgenmode = TXG_NO_TEX_GEN; GLenum texenvmode = GL_DECAL; int blendmode = VP_FALSE; GLenum sblendfunc = GL_SRC_ALPHA; GLenum dblendfunc = GL_ONE_MINUS_SRC_ALPHA; int rendermode = LINEmode; int displaylistmode = VP_FALSE; GLfloat linewidthmode = 1.0F; GLfloat localviewmode = 0.0F; GLenum polymodefront = GL_FILL; GLenum polymodeback = GL_FILL; int mblurmode = VP_FALSE; GLfloat blur_amount = 0.0; int fsantimode = VP_FALSE; int fsaredraw = 0; GLfloat fsajitter = 0.0F; struct vector *jitter; int walkthrumode = VP_FALSE; int cmface = GL_FRONT; int cmmode = GL_AMBIENT_AND_DIFFUSE; int cmenable = VP_FALSE; char filename[512], *filenameptr; char objname[64], *objnameptr; char header[64]; char *depth; long pack; int row, col, index; int xpix, ypix; int numpix; int numcomp = 3; GLfloat minfilter = GL_NEAREST; GLfloat magfilter = GL_NEAREST; unsigned char *Image; unsigned char *TextureImage; RenderIndex rfindex; EventLoopIndex elindex; struct RenderBlock renderblock; struct ThreadBlock *tb; GLfloat * trans = eventblock.trans; GLfloat * center = eventblock.center; EnvironmentInfo environ; char *leader = OUTPUT_LEADER; int nameWidth = OUTPUT_NAME_WIDTH; environ.directRender = VP_TRUE; environ.bufConfig.doubleBuffer = VP_TRUE; environ.windowWidth = X_WINDOW_SIZE; environ.windowHeight = Y_WINDOW_SIZE; eventblock.rb = &renderblock; eventblock.numframes = 0; eventblock.minperiod = MIN_TEST_TIME; eventblock.threads = 1; filenameptr = filename; objnameptr = objname; #ifdef WIN32 LogFile = fopen("viewperf.log", "a"); #endif /* Save a copy of the command line arguments */ strcpy( cmdln , "\0" ); for( i=1 ; i< argc ; i++) { strcat(cmdln,argv[i]); strcat(cmdln," "); } /*********************************************************************/ /* */ /* Get your branch units ready ... */ /* Parse the command line args and set viewperf mode variables */ /* */ /*********************************************************************/ while (--argc) { ++argv; /*** Options accepting arguments. ***/ if (strcmp ("-backface", argv[0]) == 0 || strcmp ("-bf", argv[0]) == 0) { backfacemode = VP_TRUE; } else if (strcmp ("-frontface", argv[0]) == 0 || strcmp ("-ff", argv[0]) == 0) { frontfacemode = VP_TRUE; } else if (strcmp ("-mblur", argv[0]) == 0) { if(argc == 1) FATAL_ERROR ("viewperf: the -mblur flag requires a number of frames.\n"); mblurmode = VP_TRUE; blur_amount = atof(argv[1]); vistype |= AUX_ACCUM; ARG_INC; } else if (strcmp("-aa_multi", argv[0]) == 0) { if(argc < 3) FATAL_ERROR ("viewperf: the -aa_multi flag requires # of samples and jitter distance.\n"); fsantimode = VP_TRUE; fsaredraw = atoi(argv[1]); fsajitter = atof(argv[2]); jitter = (struct vector *)malloc((fsaredraw +1)* sizeof(struct vector)); jitter[0].x = 0; jitter[0].y = 0; jitter[0].z = 0; for(i=1; i<= fsaredraw; i++) { jitter[i].x = fsajitter * cos(2.0*PI*i/fsaredraw); jitter[i].y = fsajitter * sin(2.0*PI*i/fsaredraw); } vistype |= AUX_ACCUM; ARG_INC; ARG_INC; } else if (strcmp ("-rendermode", argv[0]) == 0 || strcmp ("-rm", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -rendermode flag requires an argument.\n"); if (strcmp ("VECTOR", argv[1]) == 0) rendermode = VECTORmode; else if (strcmp ("LINE", argv[1]) == 0) rendermode = LINEmode; else if (strcmp ("POLYGON", argv[1]) == 0) rendermode = POLYGONmode; else if (strcmp ("TFAN", argv[1]) == 0) rendermode = TFANmode; else if (strcmp ("POINT", argv[1]) == 0) rendermode = POINTmode; else if (strcmp ("TMESH", argv[1]) == 0) rendermode = TMESHmode; else if (strcmp ("TRIANGLE", argv[1]) == 0) rendermode = TRImode; else if (strcmp ("QUAD", argv[1]) == 0) rendermode = QUADmode; ARG_INC; } else if (strcmp ("-linesmooth", argv[0]) == 0 || strcmp ("-ls", argv[0]) == 0) { linesmoothmode = VP_TRUE; } else if (strcmp ("-facetnormal", argv[0]) == 0 || strcmp ("-fn", argv[0]) == 0) { facetnormalmode = VP_TRUE; } else if (strcmp ("-displaylist", argv[0]) == 0 || strcmp ("-dl", argv[0]) == 0) { displaylistmode = VP_TRUE; } else if (strcmp ("-flat", argv[0]) == 0 || strcmp ("-f", argv[0]) == 0) { shademodelmode = GL_FLAT; } else if (strcmp ("-indirectrender", argv[0]) == 0 || strcmp ("-ir", argv[0]) == 0) { environ.directRender = VP_FALSE; } else if (strcmp ("-vaccum", argv[0]) == 0 || strcmp ("-vac", argv[0]) == 0) { vistype |= AUX_ACCUM; } else if (strcmp ("-valpha", argv[0]) == 0 || strcmp ("-val", argv[0]) == 0) { vistype |= AUX_ALPHA; } else if (strcmp ("-vdepthbuffer", argv[0]) == 0 || strcmp ("-vz", argv[0]) == 0) { vistype |= AUX_DEPTH; } else if (strcmp ("-vstencil", argv[0]) == 0 || strcmp ("-vst", argv[0]) == 0) { vistype |= AUX_STENCIL; } else if (strcmp ("-vid", argv[0]) == 0 ) { if (argc == 1) FATAL_ERROR ("viewperf: the -vid flag requires an argument.\n"); vis_id = atoi (argv[1]); vis_criteria = AUX_USE_ID; strcpy( txcriteria , "ID" ); ARG_INC; } else if (strcmp ("-vcriteria", argv[0]) == 0 || strcmp ("-vcrit", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -vcriteria flag requires an argument.\n"); if (strcmp ("EXACT", argv[1]) == 0) { vis_criteria = AUX_EXACT_MATCH; strcpy( txcriteria , "EXACT" ); } else if (strcmp ("MIN", argv[1]) == 0) { vis_criteria = AUX_MINIMUM_CRITERIA; strcpy( txcriteria , "MINIMUM" ); } ARG_INC; } else if (strcmp ("-singlebuffer", argv[0]) == 0 || strcmp ("-sb", argv[0]) == 0) { renderDoubleBuffer = VP_FALSE; } else if (strcmp ("-ortho", argv[0]) == 0 || strcmp ("-or", argv[0]) == 0) { orthomode = VP_TRUE; } else if (strcmp ("-nodither", argv[0]) == 0 || strcmp ("-ndi", argv[0]) == 0) { dithermode = VP_FALSE; } else if (strcmp ("-blend", argv[0]) == 0 || strcmp ("-bl", argv[0]) == 0) { blendmode = VP_TRUE; } else if (strcmp ("-zbuffer", argv[0]) == 0 || strcmp ("-zb", argv[0]) == 0) { zbuffermode = VP_TRUE; } else if (strcmp ("-linestipple", argv[0]) == 0 || strcmp ("-lp", argv[0]) == 0) { linestipplemode = VP_TRUE; } else if (strcmp ("-polystipple", argv[0]) == 0 || strcmp ("-pp", argv[0]) == 0) { polystipplemode = VP_TRUE; } else if (strcmp ("-fog", argv[0]) == 0 || strcmp ("-fg", argv[0]) == 0) { fogmode = VP_TRUE; } else if (strcmp ("-clip", argv[0]) == 0 || strcmp ("-c", argv[0]) == 0) { clipmode = VP_TRUE; } else if (strcmp ("-lighttwoside", argv[0]) == 0 || strcmp ("-l2s", argv[0]) == 0) { lighttwoside = GL_TRUE; } else if (strcmp ("-localview", argv[0]) == 0 || strcmp ("-lv", argv[0]) == 0) { localviewmode = 1.0F; } else if (strcmp ("-toggle", argv[0]) == 0 || strcmp ("-tg", argv[0]) == 0) { togglemode = VP_TRUE; if (argc == 1) FATAL_ERROR ("viewperf: the -toggle flag requires an argument.\n"); if (strcmp ("DEPTH_TEST", argv[1]) == 0) { renderblock.capability = GL_DEPTH_TEST; strcpy( txtoggle , "DEPTH_TEST" ); } else if (strcmp ("DITHER", argv[1]) == 0) { renderblock.capability = GL_DITHER; strcpy( txtoggle , "DITHER" ); } else if (strcmp ("LIGHTING", argv[1]) == 0) { renderblock.capability = GL_LIGHTING; strcpy( txtoggle , "LIGHTING" ); } else if (strcmp ("LINE_STIPPLE", argv[1]) == 0) { renderblock.capability = GL_LINE_STIPPLE; strcpy( txtoggle , "LINE_STIPPLE" ); } else if (strcmp ("BLEND", argv[1]) == 0) { renderblock.capability = GL_BLEND; strcpy( txtoggle , "BLEND" ); } else if (strcmp ("POLYGON_STIPPLE", argv[1]) == 0) { renderblock.capability = GL_POLYGON_STIPPLE; strcpy( txtoggle , "POLYGON_STIPPLE" ); } else if (strcmp ("LINE_WIDTH", argv[1]) == 0) { togglelinewidthmode = VP_TRUE; strcpy( txtoggle , "LINE_WIDTH" ); } else if (strcmp ("MATRIX", argv[1]) == 0) { togglematrixmode = VP_TRUE; strcpy( txtoggle , "MATRIX" ); } ARG_INC; } else if (strcmp ("-srcblendfunc", argv[0]) == 0 || strcmp ("-sbf", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -srcblendfunc flag requires an argument.\n"); if (strcmp ("ZERO", argv[1]) == 0) { sblendfunc = GL_ZERO; strcpy( txsblendfunc , "ZERO" ); } else if (strcmp ("ONE", argv[1]) == 0) { sblendfunc = GL_ONE; strcpy( txsblendfunc , "ONE" ); } else if (strcmp ("DST_COLOR", argv[1]) == 0) { sblendfunc = GL_DST_COLOR; strcpy( txsblendfunc , "DST_COLOR" ); } else if (strcmp ("ONE_MINUS_DST_COLOR", argv[1]) == 0) { sblendfunc = GL_ONE_MINUS_DST_COLOR; strcpy( txsblendfunc , "ONE_MINUS_DST_COLOR" ); } else if (strcmp ("SRC_ALPHA", argv[1]) == 0) { sblendfunc = GL_SRC_ALPHA; strcpy( txsblendfunc , "SRC_ALPHA" ); } else if (strcmp ("ONE_MINUS_SRC_ALPHA", argv[1]) == 0) { sblendfunc = GL_ONE_MINUS_SRC_ALPHA; strcpy( txsblendfunc , "ONE_MINUS_SRC_ALPHA" ); } else if (strcmp ("DST_ALPHA", argv[1]) == 0) { sblendfunc = GL_DST_ALPHA; strcpy( txsblendfunc , "DST_ALPHA" ); } else if (strcmp ("ONE_MINUS_DST_ALPHA", argv[1]) == 0) { sblendfunc = GL_ONE_MINUS_DST_ALPHA; strcpy( txsblendfunc , "ONE_MINUS_DST_ALPHA" ); } else if (strcmp ("SRC_ALPHA_SATURATE", argv[1]) == 0) { sblendfunc = GL_SRC_ALPHA_SATURATE; strcpy( txsblendfunc , "SRC_ALPHA_SATURATE" ); } ARG_INC; } else if (strcmp ("-dstblendfunc", argv[0]) == 0 || strcmp ("-dbf", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -dstblendfunc flag requires an argument.\n"); if (strcmp ("ZERO", argv[1]) == 0) { dblendfunc = GL_ZERO; strcpy( txdblendfunc , "ZERO" ); } else if (strcmp ("ONE", argv[1]) == 0) { dblendfunc = GL_ONE; strcpy( txdblendfunc , "ONE" ); } else if (strcmp ("SRC_COLOR", argv[1]) == 0) { dblendfunc = GL_SRC_COLOR; strcpy( txdblendfunc , "SRC_COLOR" ); } else if (strcmp ("ONE_MINUS_SRC_COLOR", argv[1]) == 0) { dblendfunc = GL_ONE_MINUS_SRC_COLOR; strcpy( txdblendfunc , "ONE_MINUS_SRC_COLOR" ); } else if (strcmp ("SRC_ALPHA", argv[1]) == 0) { dblendfunc = GL_SRC_ALPHA; strcpy( txdblendfunc , "SRC_ALPHA" ); } else if (strcmp ("ONE_MINUS_SRC_ALPHA", argv[1]) == 0) { dblendfunc = GL_ONE_MINUS_SRC_ALPHA; strcpy( txdblendfunc , "ONE_MINUS_SRC_ALPHA" ); } else if (strcmp ("DST_ALPHA", argv[1]) == 0) { dblendfunc = GL_DST_ALPHA; strcpy( txdblendfunc , "DST_ALPHA" ); } else if (strcmp ("ONE_MINUS_DST_ALPHA", argv[1]) == 0) { dblendfunc = GL_ONE_MINUS_DST_ALPHA; strcpy( txdblendfunc , "ONE_MINUS_DST_ALPHA" ); } ARG_INC; } else if (strcmp ("-polysmooth", argv[0]) == 0 || strcmp ("-ps", argv[0]) == 0) { polysmoothmode = VP_TRUE; sblendfunc = GL_SRC_ALPHA_SATURATE; strcpy( txsblendfunc , "SRC_ALPHA_SATURATE" ); dblendfunc = GL_ONE; strcpy( txdblendfunc , "ONE" ); } else if (strcmp ("-batch", argv[0]) == 0 || strcmp ("-bt", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -batch flag requires an argument.\n"); batchmode = VP_TRUE; numtobatch = atoi (argv[1]); ARG_INC; } else if (strcmp ("-colorper", argv[0]) == 0 || strcmp ("-cp", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -colorper flag requires an argument.\n"); if (strcmp ("FRAME", argv[1]) == 0) { colormode = COLOR_PER_FRAME; strcpy( txcolormode , "COLOR_PER_FRAME" ); } else if (strcmp ("PRIMITIVE", argv[1]) == 0) { colormode = COLOR_PER_PRIMITIVE; strcpy( txcolormode , "COLOR_PER_PRIMITIVE" ); } else if (strcmp ("VERTEX", argv[1]) == 0) { colormode = COLOR_PER_VERTEX; strcpy( txcolormode , "COLOR_PER_VERTEX" ); } ARG_INC; } else if (strcmp ("-texcomp", argv[0]) == 0 || strcmp ("-tc", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -texcomp flag requires an argument.\n"); numcomp = atoi (argv[1]); if (numcomp < 1 || numcomp > 4) numcomp = 3; ARG_INC; } else if (strcmp ("-texenv", argv[0]) == 0 || strcmp ("-te", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -texenv flag requires an argument.\n"); if (strcmp ("MODULATE", argv[1]) == 0) { texenvmode = GL_MODULATE; strcpy( txenv , "MODULATE" ); } else if (strcmp ("BLEND", argv[1]) == 0) { texenvmode = GL_BLEND; strcpy( txenv , "BLEND" ); } else if (strcmp ("DECAL", argv[1]) == 0) { texenvmode = GL_DECAL; strcpy( txenv , "DECAL" ); } ARG_INC; } else if (strcmp ("-texgen", argv[0]) == 0 || strcmp ("-txg", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -texgen flag requires an argument.\n"); texgenmode = TXG_EYE_LINEAR; strcpy( txfile , argv[1]); #ifdef SEARCHPATH { char* texpath = getenv("VPTEXPATH"); char* dataPath; char filenameptr[512]; char* defaultPath = ".:./data/textures:/"; if (texpath == 0) texpath = defaultPath; else if (*texpath == 0) texpath = defaultPath; if (txfile) { strcpy(filenameptr, txfile); dataPath = SearchPath(texpath, filenameptr); if (dataPath == NULL) FATAL_ERROR("Couldn't open texture file\n"); /* Add dataPath to the beginning of txfile */ strcat(dataPath, "/"); strcpy(txfile, strcat(dataPath, txfile)); } } #endif if ((texfile = fopen(txfile, BINARY_FILE) ) == 0) { FATAL_ERROR("Can't open texture file\n"); } ARG_INC; if( (argc != 1) && (argv[1][0] != '-') ) { if(!strcmp(argv[1], "OBJECT_LINEAR")) texgenmode = TXG_OBJECT_LINEAR; else if(!strcmp(argv[1], "SPHERE_MAP")) texgenmode = TXG_SPHERE_MAP; } } else if (strcmp ("-texture", argv[0]) == 0 || strcmp ("-tx", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -texture flag requires an argument.\n"); texturemode = VP_TRUE; strcpy( txfile , argv[1]); #ifdef SEARCHPATH { char* texpath = getenv("VPTEXPATH"); char* dataPath; char filenameptr[512]; char* defaultPath = ".:./data/textures:/"; if (texpath == 0) texpath = defaultPath; else if (*texpath == 0) texpath = defaultPath; if (txfile) { strcpy(filenameptr, txfile); dataPath = SearchPath(texpath, filenameptr); if (dataPath == NULL) FATAL_ERROR("Couldn't open texture file\n"); /* Add dataPath to the beginning of txfile */ strcat(dataPath, "/"); strcpy(txfile, strcat(dataPath, txfile)); } } #endif if ((texfile = fopen(txfile, BINARY_FILE) ) == 0) { FATAL_ERROR("Can't open texture file\n"); } ARG_INC; } else if (strcmp ("-minfilter", argv[0]) == 0 || strcmp ("-minf", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -minfilter flag requires an argument.\n"); if (strcmp ("NEAREST", argv[1]) == 0) { minfilter = GL_NEAREST; strcpy( txmin , "NEAREST" ); } else if (strcmp ("LINEAR", argv[1]) == 0) { minfilter = GL_LINEAR; strcpy( txmin , "LINEAR" ); } else if (strcmp ("NEAREST_MIPMAP_NEAREST", argv[1]) == 0) { minfilter = GL_NEAREST_MIPMAP_NEAREST; strcpy( txmin , "NEAREST_MIPMAP_NEAREST" ); } else if (strcmp ("LINEAR_MIPMAP_LINEAR", argv[1]) == 0) { minfilter = GL_LINEAR_MIPMAP_LINEAR; strcpy( txmin , "LINEAR_MIPMAP_LINEAR" ); } else if (strcmp ("NEAREST_MIPMAP_LINEAR", argv[1]) == 0) { minfilter = GL_NEAREST_MIPMAP_LINEAR; strcpy( txmin , "NEAREST_MIPMAP_LINEAR" ); } else if (strcmp ("LINEAR_MIPMAP_LINEAR", argv[1]) == 0) { minfilter = GL_LINEAR_MIPMAP_LINEAR; strcpy( txmin , "LINEAR_MIPMAP_LINEAR" ); } ARG_INC; } else if (strcmp ("-magfilter", argv[0]) == 0 || strcmp ("-magf", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -magfilter flag requires an argument.\n"); if (strcmp ("NEAREST", argv[1]) == 0) { magfilter = GL_NEAREST; strcpy( txmag , "NEAREST" ); } else if (strcmp ("LINEAR", argv[1]) == 0) { magfilter = GL_LINEAR; strcpy( txmag , "LINEAR" ); } ARG_INC; } else if (strcmp ("-colormaterial", argv[0]) == 0 || strcmp ("-cm", argv[0]) == 0) { if (argc < 3) FATAL_ERROR ("viewperf: the -colormaterial flag requires 2 arguments.\n"); if (strcmp ("FRONT", argv[1]) == 0) { cmface = GL_FRONT; strcpy( cmfaceString , "FRONT" ); } else if (strcmp ("BACK", argv[1]) == 0) { cmface = GL_BACK; strcpy( cmfaceString , "BACK" ); } else if (strcmp ("FRONT_AND_BACK", argv[1]) == 0) { cmface = GL_FRONT_AND_BACK; strcpy( cmfaceString , "FRONT_AND_BACK" ); } if (strcmp ("EMISSION", argv[2]) == 0) { cmmode = GL_EMISSION; strcpy( cmmodeString , "EMISSION" ); } else if (strcmp ("AMBIENT", argv[2]) == 0) { cmmode = GL_AMBIENT; strcpy( cmmodeString , "AMBIENT" ); } else if (strcmp ("DIFFUSE", argv[2]) == 0) { cmmode = GL_DIFFUSE; strcpy( cmmodeString , "DIFFUSE" ); } else if (strcmp ("SPECULAR", argv[2]) == 0) { cmmode = GL_SPECULAR; strcpy( cmmodeString , "SPECULAR" ); } else if (strcmp ("AMBIENT_AND_DIFFUSE", argv[2]) == 0) { cmmode = GL_AMBIENT_AND_DIFFUSE; strcpy( cmmodeString , "AMBIENT_AND_DIFFUSE" ); } ARG_INC; } else if (strcmp ("-polymodefront", argv[0]) == 0 || strcmp ("-pmf", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -polymodefront flag requires an argument.\n"); if (strcmp ("FILL", argv[1]) == 0) { polymodefront = GL_FILL; strcpy( txpmf , "FILL" ); } else if (strcmp ("POINT", argv[1]) == 0) { polymodefront = GL_POINT; strcpy( txpmf , "POINT" ); } else if (strcmp ("LINE", argv[1]) == 0) { polymodefront = GL_LINE; strcpy( txpmf , "LINE" ); } ARG_INC; } else if (strcmp ("-polymodeback", argv[0]) == 0 || strcmp ("-pmb", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -polymodeback flag requires an argument.\n"); if (strcmp ("FILL", argv[1]) == 0) { polymodeback = GL_FILL; strcpy( txpmb , "FILL" ); } else if (strcmp ("POINT", argv[1]) == 0) { polymodeback = GL_POINT; strcpy( txpmb , "POINT" ); } else if (strcmp ("LINE", argv[1]) == 0) { polymodeback = GL_LINE; strcpy( txpmb , "LINE" ); } ARG_INC; } else if (strcmp ("-triangle", argv[0]) == 0 || strcmp ("-tr", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -triangle flag requires an argument.\n"); objnameptr = strcpy(objnameptr, argv[1]); inputmode = TRIINPUT; ARG_INC; } else if (strcmp ("-quad", argv[0]) == 0 || strcmp ("-qd", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -quad flag requires an argument.\n"); objnameptr = strcpy(objnameptr, argv[1]); inputmode = QUADINPUT; ARG_INC; } else if (strcmp ("-mesh", argv[0]) == 0 || strcmp ("-mh", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -mesh flag requires an argument.\n"); objnameptr = strcpy(objnameptr, argv[1]); inputmode = MESHINPUT; ARG_INC; } else if (strcmp ("-polygon", argv[0]) == 0 || strcmp ("-pg", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -polygon flag requires an argument.\n"); objnameptr = strcpy(objnameptr, argv[1]); inputmode = POLYGONINPUT; ARG_INC; } else if (strcmp ("-walkthru", argv[0]) == 0 || strcmp ("-wt", argv[0]) == 0) { walkthrumode = VP_TRUE; } else if (strcmp ("-linewidth", argv[0]) == 0 || strcmp ("-lw", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -linewidth flag requires an argument.\n"); linewidthmode = atof (argv[1]); ARG_INC; } else if (strcmp ("-xwinsize", argv[0]) == 0 || strcmp ("-xws", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -xwinsize flag requires an argument.\n"); environ.windowWidth = atoi (argv[1]); ARG_INC; } else if (strcmp ("-ywinsize", argv[0]) == 0 || strcmp ("-yws", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -ywinsize flag requires an argument.\n"); environ.windowHeight = atoi (argv[1]); ARG_INC; } else if (strcmp ("-numframes", argv[0]) == 0 || strcmp ("-nf", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -numframes flag requires an argument.\n"); eventblock.numframes = atoi (argv[1]); if (eventblock.numframes <= 0) FATAL_ERROR ("viewperf: You'll need more frames than this\n"); ARG_INC; } else if (strcmp ("-numilights", argv[0]) == 0 || strcmp ("-nil", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -numilights flag requires an argument.\n"); numInfiniteLights = atoi (argv[1]); if (numInfiniteLights < 0) FATAL_ERROR ("viewperf: Number of infinite lights must be positive.\n"); if (numInfiniteLights + numLocalLights > 8) FATAL_ERROR ("viewperf: Total number of lights enabled must be less than or equal to 8.\n"); ARG_INC; } else if (strcmp ("-numllights", argv[0]) == 0 || strcmp ("-nll", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -numllights flag requires an argument.\n"); numLocalLights = atoi (argv[1]); if (numLocalLights < 0) FATAL_ERROR ("viewperf: Number of local lights must be positive.\n"); if (numInfiniteLights + numLocalLights > 8) FATAL_ERROR ("viewperf: Total number of lights enabled must be less than or equal to 8.\n"); ARG_INC; } else if (strcmp ("-minperiod", argv[0]) == 0 || strcmp ("-mp", argv[0]) == 0) { if (argc == 1) FATAL_ERROR ("viewperf: the -minperiod flag requires an argument.\n"); eventblock.minperiod = atof (argv[1]); ARG_INC; #ifdef MP } else if (strcmp ("-threads", argv[0]) == 0 || strcmp ("-th", argv[0]) == 0) { if ((argc > 1) && (isdigit(*argv[1]))) { eventblock.threads = atoi (argv[1]); ARG_INC; } else { eventblock.threads = numProcessors (); } if (eventblock.threads < 1) FATAL_ERROR ("viewperf: the minimum number of threads is 1.\n"); #endif } else if (strcmp ("-help", argv[0]) == 0 || strcmp ("-usage", argv[0]) == 0 || strcmp ("-h", argv[0]) == 0 || strcmp ("-u", argv[0]) == 0) { fprintf (stdout, "viewperf version %s:\n", VERSION); fprintf (stdout, "\ Program options:\n\ -polygon -pg <file> : Viewpoint object to be used in the tests\n\ -triangle -tr <file> : Viewpoint object to be used in the tests\n\ -quad -qd <file> : Viewpoint object to be used in the tests\n\ -mesh -mh <file> : Mesh object to be used in the tests\n\ -rendermode -rm <mode> : POINT, VECTOR, LINE, POLYGON, TMESH, TFAN,\n\ TRIANGLE, or QUAD - default LINE\n\ -vcriteria -vcrit : AUX Visual selection criteria - EXACT, MIN\n\ - default MIN\n\ -vid <id> : Ask AUX for visual with ID = <id>\n\ -vaccum -vac : Ask AUX for an accumulation buffer visual\n\ -valpha -val : Ask AUX for an alpha buffer visual\n\ -vdepthbuffer -vz : Ask AUX for a depth buffer visual\n\ -vstencil -vst : Ask AUX for a stencil buffer visual\n\ -indirectrender -ir : Render indirect - default direct\n\ -nodither -ndi : Disable dithering\n\ -ortho -or : Parallel/Orthographic projection - default Perspective\n\ -displaylist -dl : Render with display list mode\n\ -colorper -cp <mode> : FRAME = Color per Frame,\n\ : PRIMITIVE = Color per Primitive,\n\ : VERTEX = Color per Vertex - default FRAME\n\ -texture -tx <file> : MTV image for texturing\n\ -texgen -txg <file> <mode> : <file> is MTV image for environment mapping\n\ <mode> is SPHERE_MAP, OBJECT_LINEAR, EYE_LINEAR\n\ - default EYE_LINEAR\n\ -magfilter -magf <flt> : NEAREST, LINEAR - default NEAREST\n\ -minfilter -minf <flt> : NEAREST, LINEAR, NEAREST_MIPMAP_NEAREST,\n\ LINEAR_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR,\n\ LINEAR_MIPMAP_LINEAR - default NEAREST\n\ -texenv -te <env> : Texture environment, MODULATE, DECAL, BLEND\n\ - default DECAL\n\ -texcomp -tc <num> : Texture components where <num> is 1,2,3, or 4\n\ : -default 3\n\ "); fprintf (stdout, "\ -blend -bl : Enable Blending\n\ -srcblendfunc -sbf : ZERO, ONE, DST_COLOR, ONE_MINUS_DST_COLOR, SRC_ALPHA,\n\ ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA,\n\ SRC_ALPHA_SATURATE - default SRC_ALPHA\n\ -dstblendfunc -dbf : ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, SRC_ALPHA,\n\ ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA,\n\ - default ONE_MINUS_SRC_ALPHA\n\ -linewidth -lw <width> : Linewidth for wire/vector tests - default 1.0\n\ -xwinsize -xws <side> : Size of test windows X dimension - default 700\n\ -ywinsize -yws <side> : Size of test windows Y dimension - default 700\n\ -numframes -nf <num> : Number of frames to be rendered during measurement\n\ Takes priority over -mp\n\ -numilights -nil <num> : Turns on <num> infinite lights - default 0\n\ -numllights -nll <num> : Turns on <num> local lights - default 0\n\ "); fprintf (stdout, "\ -colormaterial -cm <side> <mode> :\n\ <side> is FRONT, BACK, FRONT_AND_BACK - default FRONT\n\ <mode> is AMBIENT, DIFFUSE, EMISSION, SPECULAR,\n\ AMBIENT_AND_DIFFUSE - default AMBIENT_AND_DIFFUSE\n\ -backface -bf : Cull Backfacing primitives - default off\n\ -frontface -ff : Cull Frontfacing primitives - default off\n\ -singlebuffer -sb : Single buffer mode\n\ -fog -fg : Enable fog\n\ -linesmooth -ls : Enable line antialiasing\n\ -polysmooth -ps : Enable polygon antialiasing\n\ -facetnormal -fn : Use facet normals when lighting\n\ -linestipple -lp : Enable line stipple\n\ -polystipple -pp : Enable polygon stipple\n\ -toggle -tg <cap> : Toggle per primitive - BLEND, DEPTH_TEST, DITHER,\n\ LIGHTING, LINE_WIDTH, LINE_STIPPLE, POLYGON_STIPPLE,\n\ or MATRIX - multmatrix\n\ -batch -bt <num> : Batch <num> primitives together per glBegin/glEnd\n\ Valid with POINT, VECTOR, TRIANGLE, and QUADS\n\ -polymodefront -pmf : POINT, LINE, or FILL - default FILL\n\ -polymodeback -pmb : POINT, LINE, or FILL - default FILL\n\ -flat -f : Set shademodel to FLAT - default GOURAUD\n\ -zbuffer -zb : Enable zbuffer for tests - default off\n\ "); fprintf (stdout, "\ -clip -c : Align object on 3D clip boundary\n\ -lighttwoside -l2s : Light both sides of model\n\ -localview -lv : Define local viewer for lit tests\n\ -minperiod -mp <num> : Set minimum testing period in seconds\n\ -mblur <num> : Use motion blur with num being amount of decay\n\ -aa_multi <x> <r> : Full scene antialiasing rendered x times at an\n\ : offset of r. r should be tuned to the viewset\n\ -walkthru -wt : Walkthru mode\n\ "); #ifdef MP fprintf (stdout, "\ -threads -th <num> : Sets number of threads (no arg means 1 per processor)\n\ "); #endif exit(0); } } /*********************************************************************/ /* */ /* Test Description */ /* */ /*********************************************************************/ strcpy( desc , "\0" ); /* Input mode & Object */ strcat( desc , inputmodetx[ inputmode ] ); ptr=(ptr=strrchr(objnameptr,'/')) == NULL ? ptr=objnameptr : ++ptr; strcat( desc , ptr ); strcat( desc , " "); /* -rm */ strcat( desc , "-rm "); strcat(desc, rendermodetext[rendermode]); strcat( desc, " "); /* -cm */ if (colormode != COLOR_PER_FRAME && numInfiniteLights + numLocalLights > 0) { cmenable = VP_TRUE; } /* -nf and -mp */ if (eventblock.numframes > 0) { eventblock.minperiod = 0.0F; sprintf( tempstring , "-nf %d \0", eventblock.numframes); strcat( desc , tempstring ); } else if (eventblock.minperiod != MIN_TEST_TIME) { if ((float)floor(eventblock.minperiod) == eventblock.minperiod) { int mp = (int)eventblock.minperiod; sprintf( tempstring , "-mp %d \0", mp); strcat( desc , tempstring ); } else { sprintf( tempstring , "-mp %f \0", eventblock.minperiod); strcat( desc , tempstring ); } } /* -cp */ strcat( desc , "-cp "); strcat(desc, cptx[colormode]); strcat( desc , dr[environ.directRender]); strcat( desc , dl[displaylistmode]); strcat( desc , db[renderDoubleBuffer]); strcat( desc , zb[zbuffermode]); strcat( desc , fg[fogmode]); /* -bt */ if ( numtobatch != 0 ) { sprintf( tempstring,"-bt %d \0",numtobatch); strcat( desc, tempstring ); } strcat( desc , shade[shademodelmode == GL_FLAT]); /* -nil */ if ( numInfiniteLights > 0 ) { sprintf( tempstring , "-nil %d \0", numInfiniteLights); strcat( desc , tempstring ); } /* -nll */ if ( numLocalLights > 0 ) { sprintf( tempstring , "-nll %d \0", numLocalLights); strcat( desc , tempstring ); } if ( cmenable && ( cmface != GL_FRONT || cmmode != GL_AMBIENT_AND_DIFFUSE ) ) { sprintf( tempstring , "-cm %s %s \0", cmfaceString, cmmodeString); strcat( desc , tempstring ); } strcat( desc , lv[(int)localviewmode]); strcat( desc , l2s[lighttwoside]); strcat( desc , or[orthomode]); strcat( desc , fn[facetnormalmode]); strcat( desc , bf[backfacemode]); strcat( desc , ff[frontfacemode]); strcat( desc , pp[polystipplemode]); strcat( desc , ps[polysmoothmode]); strcat( desc , lp[linestipplemode]); strcat( desc , ls[linesmoothmode]); /* -lw */ if ( linewidthmode > 1.0 ) { sprintf( tempstring , "-lw %0.1f \0", linewidthmode); strcat( desc , tempstring ); } strcat( desc , di[dithermode]); strcat( desc , clip[clipmode]); /* -pmf */ if (strcmp("FILL", txpmf) != 0) { sprintf(tempstring,"-pmf %s \0",txpmf); strcat(desc,tempstring); } /* -pmb */ if (strcmp("FILL", txpmb) != 0) { sprintf(tempstring,"-pmb %s \0",txpmb); strcat(desc,tempstring); } /* -tg */ if (togglemode) { sprintf(tempstring,"-tg %s \0",txtoggle); strcat(desc,tempstring); } strcat( desc , bl[blendmode]); /* -sbf */ if (strcmp("SRC_ALPHA",txsblendfunc)!=0) { sprintf(tempstring,"-sbf %s \0",txsblendfunc); strcat(desc,tempstring); } /* -dbf */ if (strcmp("ONE_MINUS_SRC_ALPHA",txdblendfunc)!=0) { sprintf(tempstring,"-dbf %s \0",txdblendfunc); strcat(desc,tempstring); } /* -tx */ if( texturemode ) { ptr=(ptr=strrchr(txfile,'/')) == NULL ? ptr=txfile : ++ptr; sprintf(tempstring,"-tx %s ", ptr); strcat( desc , tempstring ); if (strcmp("NEAREST", txmag) != 0) { sprintf(tempstring,"-magf %s \0",txmag); strcat(desc,tempstring); } if (strcmp("NEAREST", txmin) != 0) { sprintf(tempstring,"-minf %s \0",txmin); strcat(desc,tempstring); } if (strcmp("DECAL", txenv) != 0) { sprintf(tempstring,"-te %s \0" ,txenv); strcat(desc,tempstring); } if ( numcomp != 3) { sprintf(tempstring,"-tc %d \0" ,numcomp); strcat(desc,tempstring); } } /* -txg */ if( texgenmode ) { ptr=(ptr=strrchr(txfile,'/')) == NULL ? ptr=txfile : ++ptr; sprintf(tempstring,"-txg %s %s ", ptr, texture_generation_mode[texgenmode]); strcat( desc , tempstring ); if (strcmp("NEAREST", txmag) != 0) { sprintf(tempstring,"-magf %s \0",txmag); strcat(desc,tempstring); } if (strcmp("NEAREST", txmin) != 0) { sprintf(tempstring,"-minf %s \0",txmin); strcat(desc,tempstring); } if (strcmp("DECAL", txenv) != 0) { sprintf(tempstring,"-te %s \0" ,txenv); strcat(desc,tempstring); } if ( numcomp != 3) { sprintf(tempstring,"-tc %d \0" ,numcomp); strcat(desc,tempstring); } } /* -xws, -yws */ if( environ.windowWidth != X_WINDOW_SIZE ) { sprintf( tempstring , "-xws %d ",environ.windowWidth); strcat( desc , tempstring ); } if( environ.windowHeight != Y_WINDOW_SIZE ) { sprintf( tempstring , "-yws %d ",environ.windowHeight); strcat( desc , tempstring ); } /* -vcrit */ if ( vis_criteria == AUX_EXACT_MATCH ) strcat( desc , "-vcrit EXACT "); strcat( desc , vac[(vistype & AUX_ACCUM) == AUX_ACCUM]); strcat( desc , val[(vistype & AUX_ALPHA) == AUX_ALPHA]); strcat( desc , vz[(vistype & AUX_DEPTH) == AUX_DEPTH]); strcat( desc , vst[(vistype & AUX_STENCIL) == AUX_STENCIL]); /* -mblur */ if(mblurmode) { sprintf( tempstring, "-mblur %f ", blur_amount); strcat( desc, tempstring); } /* -aa_multi */ if(fsantimode) { sprintf(tempstring, "-aa_multi %d %f ", fsaredraw, fsajitter); strcat(desc, tempstring); } /* -walkthru */ if(walkthrumode) { sprintf(tempstring, "-wt "); strcat(desc, tempstring); } /*********************************************************************/ /* */ /* Open Window */ /* */ /*********************************************************************/ /* if the user didn't select any visual buffers then select some for him */ if (vistype == 0) { if (zbuffermode) vistype |= AUX_DEPTH; if (blendmode && (sblendfunc == GL_DST_ALPHA || sblendfunc == GL_ONE_MINUS_DST_ALPHA || sblendfunc == GL_SRC_ALPHA_SATURATE || dblendfunc == GL_DST_ALPHA || dblendfunc == GL_ONE_MINUS_DST_ALPHA)) vistype |= AUX_ALPHA; } /* Add these to what the user or viewperf selected */ vistype |= AUX_RGB; vistype |= (renderDoubleBuffer) ? AUX_DOUBLE : AUX_SINGLE; vistype |= (environ.directRender) ? AUX_DIRECT : AUX_INDIRECT; /* set AUX visual selection criteria */ auxInitDisplayModePolicy(vis_criteria); if (vis_criteria == AUX_USE_ID ) auxInitDisplayModeID(vis_id); else auxInitDisplayMode(vistype); /* Open the window */ auxInitPosition(0, 0, environ.windowWidth, environ.windowHeight); if (auxInitWindow("Viewperf") == GL_FALSE) { fprintf(stderr, "AUX couldn't find a visual matching the given criteria\n"); auxQuit(); } /* Begin Windowing System Dependent */ #ifdef WIN32 eventblock.window = auxGetHWND(); eventblock.display = auxGetHDC(); #elif !defined(OS2) && !defined(__amigaos__) eventblock.window = auxXWindow(); eventblock.display = auxXDisplay(); #endif NullEnvironmentData(&environ); GetEnvironment(&environ); /* End Windowing System Dependent */ /*********************************************************************/ /* */ /* Render title screen */ /* */ /*********************************************************************/ glClearColor(0.0F, 0.0F, 0.0F, 1.0F); glDrawBuffer(GL_FRONT_AND_BACK); glClear(GL_COLOR_BUFFER_BIT); if (renderDoubleBuffer && environ.bufConfig.doubleBuffer) glDrawBuffer(GL_BACK); else glDrawBuffer(GL_FRONT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0F, 1280.0F, 0.0F, 1024.0F, 1.0F, -1.0F); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glShadeModel(GL_SMOOTH); glBegin(GL_QUADS); glColor3f(1.0F, 0.9F, 0.3F); glVertex2f(0.0F, 0.0F); glColor3f(1.0F, 0.9F, 0.3F); glVertex2f(1280.0F, 0.0F); glColor3f(0.6F, 0.1F, 0.9F); glVertex2f(1280.0F, 1024.0F); glColor3f(0.6F, 0.1F, 0.9F); glVertex2f(0.0F, 1024.0F); glEnd(); glLineWidth(4.0F); glColor3f(0.0F, 0.0F, 0.0F); DrawString(" OpenGL ", 172.0F, 602.0F); glLineWidth(3.0F); glColor3f(1.0F, 1.0F, 0.0F); DrawString(" OpenGL ", 170.0F, 600.0F); glLineWidth(4.0F); glColor3f(0.0F, 0.0F, 0.0F); DrawString(" Viewperf ", 172.0F, 477.0F); glLineWidth(3.0F); glColor3f(0.0F, 1.0F, 0.0F); DrawString(" Viewperf ", 170.0F, 475.0F); glLineWidth(4.0F); glColor3f(0.0F, 0.0F, 0.0F); DrawString("Loading Data Set", 172.0F, 352.0F); glLineWidth(3.0F); glColor3f(0.0F, 0.7F, 1.0F); DrawString("Loading Data Set", 170.0F, 350.0F); if (renderDoubleBuffer && environ.bufConfig.doubleBuffer) auxSwapBuffers(); /* Create thread blocks */ eventblock.tb = (struct ThreadBlock *)calloc(eventblock.threads, sizeof(struct ThreadBlock)); /*********************************************************************/ /* */ /* Read Data Set in */ /* */ /*********************************************************************/ #ifdef SEARCHPATH if (inputmode != NOINPUT) { char* objpath = getenv("VPGEOMPATH"); char* dataPath; char filenameptr[512]; char* defaultPath = ".:./data/geometry/object:./data/geometry/mesh:/"; if (objpath == 0) objpath = defaultPath; else if (*objpath == 0) objpath = defaultPath; if (objnameptr) { if (inputmode == MESHINPUT) { /* Look for objnameptr file in objpath */ strcpy(filenameptr, objnameptr); strcat(filenameptr, extension[4]); dataPath = SearchPath(objpath, filenameptr); if (dataPath == NULL) { FATAL_ERROR("Couldn't open mesh file\n"); } } else { /* Look for three files */ for (i=0; i<3; i++) { strcpy(filenameptr, objnameptr); strcat(filenameptr, extension[i]); dataPath = SearchPath(objpath, filenameptr); if (dataPath == NULL) { fprintf(stdout, "%s\n", filenameptr); FATAL_ERROR("Couldn't open input file\n"); } } } /* Add dataPath to the beginning of objnameptr */ strcat(dataPath, "/"); strcpy(objnameptr, strcat(dataPath, objnameptr)); } } #endif switch (inputmode) { case NOINPUT: fprintf(stderr, "No input file specified\n"); exit(0); break; case POLYGONINPUT: polygoninput(objnameptr, &eventblock); if (texturemode) param_poly(&eventblock); break; case MESHINPUT: meshinput(objnameptr, &eventblock); if (texturemode) param_mesh(&eventblock); break; case TRIINPUT: triquadinput(objnameptr, 3, &eventblock); if (texturemode) param_poly(&eventblock); break; case QUADINPUT: triquadinput(objnameptr, 4, &eventblock); if (texturemode) param_poly(&eventblock); break; } if (walkthrumode) { walkthruinput(objnameptr, &eventblock); } /*********************************************************************/ /* */ /* Output test info */ /* */ /*********************************************************************/ /* * Viewperf program information */ fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Viewperf Version", VERSION); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Viewperf Arguments", cmdln); /* * Test Environment Information */ PrintEnvironment(stdout, &environ, NULL, leader, nameWidth, NULL); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Visual Selection Criteria", txcriteria); fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Number of Execution Threads", eventblock.threads); /* * General viewperf test information */ fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Geometry File", objnameptr); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Input Mode", inputmodetx[ inputmode ]); fprintf(stdout, "%s%*s%f\n", leader, nameWidth, "Minimum Test Period", eventblock.minperiod); fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Number of Frames", eventblock.numframes); fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Number of Primitives", renderblock.np); fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Number of Vertices per Frame", vertsperframe); fprintf(stdout, "%s%*s%f\n", leader, nameWidth, "Number of Vertices per Primitive", ((GLfloat) vertsperframe) / ((GLfloat) renderblock.np)); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Toggle Mode", txtoggle); fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Batching Count", numtobatch); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Render Mode", rendermodetext[rendermode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Color per", txcolormode); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Orthographic Projection", falsetrue[orthomode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Display List", falsetrue[displaylistmode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Clip Geometry", falsetrue[clipmode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Walkthrough Mode", falsetrue[walkthrumode]); /* * Polygon information */ fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Back Face Cull", falsetrue[backfacemode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Front Face Cull", falsetrue[frontfacemode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Front Polygon Mode", txpmf); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Back Polygon Mode", txpmb); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Polygon Stipple Enable", falsetrue[polystipplemode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Polygon Antialiasing Enable", falsetrue[polysmoothmode]); /* * Line information */ fprintf(stdout, "%s%*s%f\n", leader, nameWidth, "Line Width", linewidthmode); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Line Stipple Enable", falsetrue[linestipplemode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Line Antialiasing Enable", falsetrue[linesmoothmode]); /* * Lighting/Shading information */ fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Number of Infinite Lights", numInfiniteLights); fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Number of Local Lights", numLocalLights); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Color Material Enable", falsetrue[(int)cmenable]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Color Material Face", cmfaceString); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Color Material Mode", cmmodeString); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Facet Normals", falsetrue[facetnormalmode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Two Sided Lighting Enable", falsetrue[(int)lighttwoside]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Local Viewer Enable", falsetrue[(int)localviewmode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Flat Shading", falsetrue[shademodelmode==GL_FLAT]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Fog Enable", falsetrue[fogmode]); /* * Texturing information */ fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Texture Enable", falsetrue[texturemode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Texture Generation Mode", texture_generation_mode[texgenmode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Texture File", txfile); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Texture Minification Filter", txmin); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Texture Magnification Filter", txmag); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Texture Environment Mode", txenv); fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Texture Components", numcomp); /* * Fragment Rasterization Information */ fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Depth Test Enable", falsetrue[zbuffermode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Blend Enable", falsetrue[blendmode]); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Source Blend Function", txsblendfunc); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Destination Blend Function", txdblendfunc); fprintf(stdout, "%s%*s%s\n", leader, nameWidth, "Dithering Enable", falsetrue[dithermode]); fprintf(stdout, "%s%*s%f\n", leader, nameWidth, "Motion Blur Amount", blur_amount); fprintf(stdout, "%s%*s%d\n", leader, nameWidth, "Full Scene Antialiasing Redraws", fsaredraw); fprintf(stdout, "%s%*s%f\n", leader, nameWidth, "Full Scene Antialiasing Jitter Amount", fsajitter); FreeEnvironmentData(&environ); /*********************************************************************/ /* */ /* Compute address into jump table for each renderer */ /* */ /*********************************************************************/ eventblock.teststring = desc; rfindex.word = 0; rfindex.bits.Texture = texturemode; switch (inputmode) { case MESHINPUT: switch (rendermode) { case POLYGONmode: case TFANmode: case TRImode: case QUADmode: fprintf(stderr, "Rendermode %s not available for mesh objects\n", rendermodetext[rendermode]); exit(0); break; case POINTmode: renderblock.mode = GL_POINTS; break; case VECTORmode: renderblock.mode = GL_LINES; break; case LINEmode: renderblock.mode = GL_LINE_STRIP; break; case TMESHmode: renderblock.mode = GL_TRIANGLE_STRIP; /* was GL_TRIANGLE_STRIP */ break; } if (blendmode || polysmoothmode) { renderblock.ColorP = glColor4fv; #ifdef FUNCTION_CALLS rfindex.bits.ColorVectorLength = COLOR4mode; #endif } else { renderblock.ColorP = glColor3fv; #ifdef FUNCTION_CALLS rfindex.bits.ColorVectorLength = COLOR3mode; #endif } if (togglemode) { if (rendermode == VECTORmode) rfindex.bits.RenderMode = BM_EXTERNAL_BY_TWO; else rfindex.bits.RenderMode = BM_EXTERNAL; if (togglelinewidthmode) { renderblock.externfunc = toggle_linewidth; } else if (togglematrixmode) { renderblock.externfunc = toggle_matrix; } else { renderblock.externfunc = toggle_capability; } } else { rfindex.bits.RenderMode = BatchTable[rendermode]; } rfindex.bits.Color = colormode; if (numInfiniteLights + numLocalLights > 0) { if (facetnormalmode) rfindex.bits.Normal = FACET_NORMmode; else rfindex.bits.Normal = VERTEX_NORMmode; } else { rfindex.bits.Normal = NO_NORMmode; } eventblock.func = MeshTable[rfindex.word]; /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->msh = &eventblock.rb->msh[thread * k]; } tb->np = eventblock.rb->np - (thread * k); tb->msh = &eventblock.rb->msh[thread * k]; break; case POLYGONINPUT: switch (rendermode) { case TMESHmode: case TRImode: case QUADmode: fprintf(stderr, "Rendermode %s not available for polygonal objects\n", rendermodetext[rendermode]); exit(0); break; case POINTmode: renderblock.mode = GL_POINTS; break; case VECTORmode: renderblock.mode = GL_LINES; break; case LINEmode: renderblock.mode = GL_LINE_LOOP; break; case POLYGONmode: renderblock.mode = GL_POLYGON; break; case TFANmode: renderblock.mode = GL_TRIANGLE_FAN; break; } if (blendmode || polysmoothmode) { renderblock.ColorP = glColor4fv; #ifdef FUNCTION_CALLS rfindex.bits.ColorVectorLength = COLOR4mode; #endif } else { renderblock.ColorP = glColor3fv; #ifdef FUNCTION_CALLS rfindex.bits.ColorVectorLength = COLOR3mode; #endif } if (togglemode) { if (rendermode == VECTORmode) rfindex.bits.RenderMode = BM_EXTERNAL_BY_TWO; else rfindex.bits.RenderMode = BM_EXTERNAL; if (togglelinewidthmode) { renderblock.externfunc = toggle_linewidth; } else if (togglematrixmode) { renderblock.externfunc = toggle_matrix; } else { renderblock.externfunc = toggle_capability; } /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; } else { if (batchmode) { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; if(numtobatch >= tb->np) { tb->batchnum = tb->np; tb->batchgroups = 1; tb->batchleftovers = 0; } else { tb->batchnum = numtobatch; tb->batchgroups = tb->np / numtobatch; tb->batchleftovers = tb->np % numtobatch; } } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; if(numtobatch >= tb->np) { tb->batchnum = tb->np; tb->batchgroups = 1; tb->batchleftovers = 0; } else { tb->batchnum = numtobatch; tb->batchgroups = tb->np / numtobatch; tb->batchleftovers = tb->np % numtobatch; } rfindex.bits.RenderMode = BatchTable[rendermode]; } else { if (rendermode == VECTORmode) { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; tb->batchnum = 1; tb->batchgroups = tb->np; tb->batchleftovers = 0; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; tb->batchnum = 1; tb->batchgroups = tb->np; tb->batchleftovers = 0; rfindex.bits.RenderMode = BM_BATCH_BY_TWO; } else { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; rfindex.bits.RenderMode = BM_NO_BATCH; } } } rfindex.bits.Color = colormode; if (numInfiniteLights + numLocalLights > 0) { if (facetnormalmode) rfindex.bits.Normal = FACET_NORMmode; else rfindex.bits.Normal = VERTEX_NORMmode; } else { rfindex.bits.Normal = NO_NORMmode; } eventblock.func = PolyTable[rfindex.word]; break; case TRIINPUT: switch (rendermode) { case TMESHmode: case QUADmode: case POLYGONmode: fprintf(stderr, "Rendermode %s not available for Triangle objects\n", rendermodetext[rendermode]); exit(0); break; case POINTmode: renderblock.mode = GL_POINTS; break; case VECTORmode: renderblock.mode = GL_LINES; break; case LINEmode: renderblock.mode = GL_LINE_LOOP; break; case TRImode: renderblock.mode = GL_TRIANGLES; break; case TFANmode: renderblock.mode = GL_TRIANGLE_FAN; break; } if (blendmode || polysmoothmode) { renderblock.ColorP = glColor4fv; #ifdef FUNCTION_CALLS rfindex.bits.ColorVectorLength = COLOR4mode; #endif } else { renderblock.ColorP = glColor3fv; #ifdef FUNCTION_CALLS rfindex.bits.ColorVectorLength = COLOR3mode; #endif } if (togglemode) { if (rendermode == VECTORmode) rfindex.bits.RenderMode = BM_EXTERNAL_BY_TWO; else rfindex.bits.RenderMode = BM_EXTERNAL; if (togglelinewidthmode) { renderblock.externfunc = toggle_linewidth; } else if (togglematrixmode) { renderblock.externfunc = toggle_matrix; } else { renderblock.externfunc = toggle_capability; } /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; } else { if (batchmode) { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; if(numtobatch >= tb->np) { tb->batchnum = tb->np; tb->batchgroups = 1; tb->batchleftovers = 0; } else { tb->batchnum = numtobatch; tb->batchgroups = tb->np / numtobatch; tb->batchleftovers = tb->np % numtobatch; } } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; if(numtobatch >= tb->np) { tb->batchnum = tb->np; tb->batchgroups = 1; tb->batchleftovers = 0; } else { tb->batchnum = numtobatch; tb->batchgroups = tb->np / numtobatch; tb->batchleftovers = tb->np % numtobatch; } rfindex.bits.RenderMode = BatchTable[rendermode]; } else { if (rendermode == VECTORmode) { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; tb->batchnum = 1; tb->batchgroups = tb->np; tb->batchleftovers = 0; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; tb->batchnum = 1; tb->batchgroups = tb->np; tb->batchleftovers = 0; rfindex.bits.RenderMode = BM_BATCH_BY_TWO; } else { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; rfindex.bits.RenderMode = BM_NO_BATCH; } } } rfindex.bits.Color = colormode; if (numInfiniteLights + numLocalLights > 0) { if (facetnormalmode) rfindex.bits.Normal = FACET_NORMmode; else rfindex.bits.Normal = VERTEX_NORMmode; } else { rfindex.bits.Normal = NO_NORMmode; } eventblock.func = TriTable[rfindex.word]; break; case QUADINPUT: switch (rendermode) { case TMESHmode: case TRImode: case POLYGONmode: fprintf(stderr, "Rendermode %s not available for Quad objects\n", rendermodetext[rendermode]); exit(0); break; case POINTmode: renderblock.mode = GL_POINTS; break; case VECTORmode: renderblock.mode = GL_LINES; break; case LINEmode: renderblock.mode = GL_LINE_LOOP; break; case QUADmode: renderblock.mode = GL_QUADS; break; case TFANmode: renderblock.mode = GL_TRIANGLE_FAN; break; } if (blendmode || polysmoothmode) { renderblock.ColorP = glColor4fv; #ifdef FUNCTION_CALLS rfindex.bits.ColorVectorLength = COLOR4mode; #endif } else { renderblock.ColorP = glColor3fv; #ifdef FUNCTION_CALLS rfindex.bits.ColorVectorLength = COLOR3mode; #endif } if (togglemode) { if (rendermode == VECTORmode) rfindex.bits.RenderMode = BM_EXTERNAL_BY_TWO; else rfindex.bits.RenderMode = BM_EXTERNAL; if (togglelinewidthmode) { renderblock.externfunc = toggle_linewidth; } else if (togglematrixmode) { renderblock.externfunc = toggle_matrix; } else { renderblock.externfunc = toggle_capability; } /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; } else { if (batchmode) { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; if(numtobatch >= tb->np) { tb->batchnum = tb->np; tb->batchgroups = 1; tb->batchleftovers = 0; } else { tb->batchnum = numtobatch; tb->batchgroups = tb->np / numtobatch; tb->batchleftovers = tb->np % numtobatch; } } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; if(numtobatch >= tb->np) { tb->batchnum = tb->np; tb->batchgroups = 1; tb->batchleftovers = 0; } else { tb->batchnum = numtobatch; tb->batchgroups = tb->np / numtobatch; tb->batchleftovers = tb->np % numtobatch; } rfindex.bits.RenderMode = BatchTable[rendermode]; } else { if (rendermode == VECTORmode) { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; tb->batchnum = 1; tb->batchgroups = tb->np; tb->batchleftovers = 0; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; tb->batchnum = 1; tb->batchgroups = tb->np; tb->batchleftovers = 0; rfindex.bits.RenderMode = BM_BATCH_BY_TWO; } else { /* Calculate per thread input data */ k = eventblock.rb->np / eventblock.threads; tb = eventblock.tb; for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) { tb->np = k; tb->ply = &eventblock.rb->ply[thread * k]; } tb->np = eventblock.rb->np - (thread * k); tb->ply = &eventblock.rb->ply[thread * k]; rfindex.bits.RenderMode = BM_NO_BATCH; } } } rfindex.bits.Color = colormode; if (numInfiniteLights + numLocalLights > 0) { if (facetnormalmode) rfindex.bits.Normal = FACET_NORMmode; else rfindex.bits.Normal = VERTEX_NORMmode; } else { rfindex.bits.Normal = NO_NORMmode; } eventblock.func = QuadTable[rfindex.word]; break; } eventblock.jitter = jitter; eventblock.redraws = fsaredraw; eventblock.blur_frames = blur_amount; eventblock.doubleBuffer = renderDoubleBuffer && environ.bufConfig.doubleBuffer; eventblock.clip = clipmode; eventblock.zbuffer = zbuffermode; /* Copy rest of RenderBlock information into ThreadBlock */ tb = eventblock.tb; for (thread = 0; thread < eventblock.threads; thread++, tb++) { tb->mode = eventblock.rb->mode; tb->capability = eventblock.rb->capability; tb->ColorP = eventblock.rb->ColorP; tb->externfunc = eventblock.rb->externfunc; tb->vert = eventblock.rb->vert; tb->vnorm = eventblock.rb->vnorm; tb->texture = eventblock.rb->texture; tb->vcolor = eventblock.rb->vcolor; } /*********************************************************************/ /* */ /* Compute address into jump table for eventloop */ /* */ /*********************************************************************/ elindex.word = 0; elindex.bits.Walkthru = walkthrumode; elindex.bits.FSAA = fsantimode; elindex.bits.BlurMode = mblurmode; elindex.bits.DisplayList = displaylistmode; eventloop = EventTable[elindex.word]; /*********************************************************************/ /* */ /* Load Texture Image */ /* */ /*********************************************************************/ if (texturemode || texgenmode) { k = 0; do { fread(&header[k], 1, 1, texfile); ++k; } while ((header[k-1] != 0) && (header[k-1] != 10)); for (i = 0; i < k; i++) if (header[i] == ' ') { header[i] = 0; depth = &header[i+1]; break; } xpix = atoi(header); ypix = atoi(depth); numpix = xpix * ypix; Image = (unsigned char *) malloc ( numpix * 3 ); TextureImage = (unsigned char *) malloc(numpix * numcomp); fread(Image, 3, numpix, texfile); fclose(texfile); switch (numcomp) { case 1 : i = 0; for (j = 0; j < numpix * 3; j += 3) { TextureImage[i++] = Image[j+1]; } break; case 2 : i = 0; for (j = 0; j < numpix * 3; j += 3) { TextureImage[i++] = Image[j]; TextureImage[i++] = 0x77; } break; case 3 : i = 0; for (j = 0; j < numpix * 3; j += 3) { TextureImage[i++] = Image[j]; TextureImage[i++] = Image[j+1]; TextureImage[i++] = Image[j+2]; } break; case 4 : i = 0; for (j = 0; j < numpix * 3; j += 3) { TextureImage[i++] = Image[j]; TextureImage[i++] = Image[j+1]; TextureImage[i++] = Image[j+2]; TextureImage[i++] = 0x77; } break; } free(Image); } /*********************************************************************/ /* */ /* Begin Rendering */ /* */ /*********************************************************************/ #ifdef WIN32 eventblock.tb[0].dc = eventblock.display; eventblock.tb[0].rc = wglGetCurrentContext(); #endif /* Initialize the contexts in the reverse order so that this thread * ends up with its own context current. */ #ifdef MP for (thread = (eventblock.threads - 1); thread >= 0; thread--) { #if defined(WIN32) if (eventblock.tb[thread].rc == NULL) eventblock.tb[thread].rc = wglCreateContext(eventblock.display); wglMakeCurrent(eventblock.display, eventblock.tb[thread].rc); #elif defined(SOME_OTHER_OS) /* Put os specific code to: Create Context Make context current */ #endif #endif if (linesmoothmode) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); } if (polysmoothmode) { glClearColor(0.0F, 0.0F, 0.0F, 0.0F); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColor4f(1.0F, 1.0F, 1.0F, 1.0F); glBlendFunc(sblendfunc, dblendfunc); glEnable(GL_BLEND); glEnable(GL_POLYGON_SMOOTH); } if (blendmode) { glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColor4f(1.0F, 1.0F, 1.0F, 0.5F); glBlendFunc(sblendfunc, dblendfunc); glEnable(GL_BLEND); } else { glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glColor3f(1.0F, 1.0F, 1.0F); } if (dithermode) { glEnable(GL_DITHER); } else { glDisable(GL_DITHER); } glPolygonMode(GL_FRONT, polymodefront); glPolygonMode(GL_BACK, polymodeback); if (linestipplemode) { glLineStipple(1, 0xf0f0); glEnable(GL_LINE_STIPPLE); } if (polystipplemode) { glPolygonStipple((const GLubyte *) stipple); glEnable(GL_POLYGON_STIPPLE); } glShadeModel(shademodelmode); if (zbuffermode) { glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); } else { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); } if (backfacemode) { glCullFace(GL_BACK); glEnable(GL_CULL_FACE); } if (frontfacemode) { glCullFace(GL_FRONT); glEnable(GL_CULL_FACE); } if (frontfacemode && backfacemode) { glCullFace(GL_FRONT_AND_BACK); glEnable(GL_CULL_FACE); } glLineWidth(linewidthmode); if (fogmode) { glFogf(GL_FOG_START, eventblock.trans[3] * ZTRANS_SCALE - maxdim); glFogf(GL_FOG_END, eventblock.trans[3] * ZTRANS_SCALE + maxdim); glFogf(GL_FOG_MODE, GL_LINEAR); glEnable(GL_FOG); } glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (walkthrumode) { if (orthomode) { /* This will NOT work well, need to do something else... */ glOrtho(-maxdim / 1.1F, maxdim / 1.1F, -maxdim / 1.1F, maxdim / 1.1F, trans[3] * ZTRANS_SCALE - maxdim, trans[3] * ZTRANS_SCALE + maxdim); } else { /* Quite arbitrary FOV, near and far planes, need something better */ gluPerspective(60.0, environ.windowWidth/environ.windowHeight, 1.0, 1000.0); } } else { if (orthomode) { glOrtho(-maxdim / 1.1F, maxdim / 1.1F, -maxdim / 1.1F, maxdim / 1.1F, trans[3] * ZTRANS_SCALE - maxdim, trans[3] * ZTRANS_SCALE + maxdim); } else { glFrustum(-maxdim / 1.6F, maxdim / 1.6F, -maxdim / 1.6F, maxdim / 1.6F, trans[3] * ZTRANS_SCALE - maxdim, trans[3] * ZTRANS_SCALE + maxdim); } } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); SetLightingState(numInfiniteLights, numLocalLights, localviewmode, lighttwoside, cmenable, cmface, cmmode, blendmode); if (texturemode || texgenmode) { switch (numcomp) { case 1: if (gluBuild2DMipmaps(GL_TEXTURE_2D, numcomp, xpix, ypix, GL_LUMINANCE, GL_UNSIGNED_BYTE, TextureImage) != 0) { fprintf(stderr, "Mipmaps didn't build\n"); exit(0); } break; case 2: if (gluBuild2DMipmaps(GL_TEXTURE_2D, numcomp, xpix, ypix, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, TextureImage) != 0) { fprintf(stderr, "Mipmaps didn't build\n"); exit(0); } break; case 3: if (gluBuild2DMipmaps(GL_TEXTURE_2D, numcomp, xpix, ypix, GL_RGB, GL_UNSIGNED_BYTE, TextureImage) != 0) { fprintf(stderr, "Mipmaps didn't build\n"); exit(0); } break; case 4: if (gluBuild2DMipmaps(GL_TEXTURE_2D, numcomp, xpix, ypix, GL_RGBA, GL_UNSIGNED_BYTE, TextureImage) != 0) { fprintf(stderr, "Mipmaps didn't build\n"); exit(0); } break; } glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texenvmode); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magfilter); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); if(texgenmode) { switch(texgenmode) { case TXG_NO_TEX_GEN: FATAL_ERROR("Hoseage has occurred in texture generation\n"); break; case TXG_EYE_LINEAR: glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); /* Was GL_EYE_LINEAR */ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); break; case TXG_OBJECT_LINEAR: glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); break; case TXG_SPHERE_MAP: glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); break; } glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glMatrixMode(GL_TEXTURE); glRotatef(180.0F, 0.0F, 0.0F, 1.0F); glTranslatef(0.5F, 0.5F, 0.0F); glScalef(1.0F / (maxdim * 2.0F), 1.0F / (maxdim * 2.0F), 1.0F / (maxdim * 2.0F)); glMatrixMode(GL_MODELVIEW); } glEnable(GL_TEXTURE_2D); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); } #ifdef MP } #endif /*********************************************************************/ /* */ /* Run the tests by calling the eventloop */ /* */ /*********************************************************************/ #ifdef MP tb = &eventblock.tb[1]; for (thread = 1; thread < eventblock.threads; thread++, tb++) { #if defined(WIN32) tb->startEvent = CreateEvent(NULL, FALSE, FALSE, NULL); tb->doneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); tb->threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)eventloop, (LPVOID)thread, 0, &tb->threadId); #elif defined(SOME_OTHER_OS) /* Put os specific code to: Create synchronization events for each thread Create each thread Call eventloop() with thread number */ #endif } #endif (*eventloop)(0); #ifdef MP tb = &eventblock.tb[1]; for (thread = 1; thread < eventblock.threads; thread++, tb++) { #if defined(WIN32) TerminateThread(tb->threadHandle, 0); #elif defined(SOME_OTHER_OS) /* Put os specific code to: Terminate threads */ #endif } #endif fprintf(stdout, "=============================================================\n"); #ifdef WIN32 fclose(LogFile); #endif auxQuit(); } #ifdef WIN32 int print_log (FILE *fo, const char *format, ...) { int count; va_list args; va_start(args, format); count = vfprintf(LogFile, format, args); fflush(LogFile); va_end(args); return count; } #endif #ifdef MP int numProcessors () { #if defined(WIN32) SYSTEM_INFO si; GetSystemInfo(&si); return (si.dwNumberOfProcessors); #elif defined(SOME_OTHER_OS) /* Put os specific code to: Return number of processors */ #endif } #endif